Python

P
PythonHub
Progress 0%

Python

  • Home
  • History of Python
  • Applications of Python
  • Introduction To Python
    • What is Python
    • Character Set
    • Tokens in Python
    • Python Execution Mode
    • Variable And Identifiers
    • Data Types in Python
    • Operators And Expressions
    • Constants in Python
    • Assignment Statement
    • Input / Output in Python
    • Simple Python Scripts
    • Namespace in Python
    • 📝 Assignments
  • Operators in Python
    • Arithmetic Operators
    • Assignment Operators
    • Shorthand Assignment Operators
    • Relational Operators
    • Logical Operators
    • Bitwise Operators
    • Special Operators
    • 📝 Assignments
  • Input Output in Python
    • Accept Input
    • Output Formatting
    • 📝 Assignments
  • Conditional Statement
    • Decision Making
    • if Statement
    • IF-ELSE STATEMENT
    • IF-ELSE LADDER
    • NESTED IF-ELSE
    • Short Hand IF-ELSE
    • 📝 Assignments
  • Loops
    • Introduction to Loops
    • While Loop
    • Nested While Loop
    • 📝 While Loop Assignments
    • For Loop
    • For Loop Examples
    • Nested For Loop
    • Nested For Loop Examples
    • Infinite While Loops
    • Infinite For Loops
    • Break, Continue and Else in Loops
    • Difference Between For and While Loop
    • For Each Loop
    • 📝 For Each Assignments
    • 📝 All Loops Assignments
  • List
    • List in Python
    • Access List Elements
    • List Functions
    • Iterate (Loop) List
    • List Comprehension
    • 📝 Assignments
  • Tuple
    • Tuple in Python
    • Access Tuple Elements
    • Tuple Functions
    • Iterate (Loop) Tuple
    • Unpack Tuple
    • Tuple Comprehension
    • 📝 Assignments
  • Set
    • Set in Python
    • Access Set Elements
    • Set Methods
    • Iterate (Loop) Set
    • Pack/Unpack Set
    • Set Comprehension
    • 📝 Assignments
  • Dictionary
    • Dictionary
    • Access Dictionary Items
    • Dictionary Methods
    • Iterate (Loop) Dictionary
    • Formatting Dictionaries
    • Nested Dictionaries
    • Dictionary Comprehension
    • 📝 Assignments
  • Diff List Tuple Set Dictionary
    • List vs Tuple
    • List vs Set
    • List vs Dictionary
    • Tuple vs Set
    • Tuple vs Dictionary
    • Dictionary vs Set
    • 📝 Assignments
  • Exception
    • Error vs Exception
    • Types of Exception
    • Exception Handling
    • User Defined Exception
    • Logging Exception
    • 📝 Assignments
  • Functions
    • Introduction to Functions
    • Modular Programming
    • Types of Functions
    • Inbuilt Functions
    • Need For User-Defined Function
    • Elements of User Defined Function
    • Function Arguments
    • Nesting of Functions
    • Recursion
    • Global Local and Non Local
    • Python Lambda Functions
    • 📝 Assignments
  • Python Module
    • Introduction to Module
    • Inbuilt Modules in Python
    • User Defined Module
    • 📝 Assignments
  • File Handling
    • Introduction to Files
    • Create File
    • Read Files
    • Write to File
    • Rename File
    • Copy File
    • Move File
    • List Files in Directory
    • Binary Files
    • Zipping and Unzipping Files
    • 📝 Assignments
  • Strings
    • Basics of Strings
    • String Special Operators
    • String Formatting Operators
    • String Methods
    • 📝 Assignments
  • Regular Expressions
  • Python OOPS
    • Basics of Object Oriented
    • What are Classes and Objects?
    • Creating Class and Object
    • OOP vs Procedural Programming
    • Difference Between Classes and Objects
    • Constructors
    • Destructor
    • Built Class Methods and Attributes
    • Class and Instance Variables
    • Inheritance in Python
    • Single Inheritance
    • Multiple Inheritance
    • Multilevel Inheritance
    • Hierarchical Inheritance
    • Hybrid Inheritance
    • Abstraction
    • Method Overriding
    • Abstract Method
    • Interfaces in Python
    • Abstract Class vs Interface
    • Public, Private and Protected
    • Overloading vs Overriding
    • Inheritance vs Composition
    • Encapsulation
    • Polymorphism
    • Inner Classes
    • 📝 Assignments
  • Advanced Python
    • Iterator in Python
    • Generator in Python
    • Decorator in Python
    • Type Hints in Python
    • Async/Await Programming
    • Dataclasses in Python
    • Context Managers in Python
    • Property Decorator in Python
    • __slots__ in Python
    • Enums in Python
    • Walrus Operator in Python
    • Match-Case in Python
    • 📝 Assignments
  • Python Standard Library
    • Collections Module
    • Itertools Module
    • Functools Module
    • Datetime Module
    • JSON Module
    • OS Module
    • Sys Module
    • Random Module
    • Math Module
    • 📝 Assignments
  • Python Testing
    • Unit Testing in Python
    • Pytest Framework
    • Mocking in Python
    • 📝 Assignments
  • Python Best Practices
    • PEP 8 Style Guide
    • Docstrings in Python
    • Logging in Python
    • Code Optimization Tips
    • Debugging Techniques
    • 📝 Assignments
  • MySQL Database in Python
    • Introduction to MySQL with Python
    • DBMS vs File System
    • Connecting to MySQL Database
    • Create Database in MySQL
    • Create Table in MySQL
    • Insert Data in MySQL
    • Insert Multiple Rows
    • Select Data from MySQL
    • WHERE Clause in MySQL
    • Update Data in MySQL
    • Delete Data from MySQL
    • Parameterized Queries
    • Transaction Management
    • Error Handling
    • Connection Pooling
    • MySQL Drivers Guide
    • Joins in MySQL
    • Aggregation Functions
    • Backup MySQL Database
    • Best Practices
    • 📝 Assignments
  • MySQL Database Operations
    • SELECT Statement
    • MySQL Operators
    • DDL Statements
    • DML Statements
    • Subqueries
    • JOIN Operations
    • Aggregation
    • Case Study
    • 📝 Assignments
  • Graphics in Python
  • Threads in Python
    • Introduction to Threads
    • Process vs Threads
    • Concurrent Programming & GIL
    • Uses of Threads
    • Creating Threads
    • Single Tasking
    • Multi Tasking
    • Thread Synchronization
    • 📝 Assignments
  • Interview Questions & Answers
  • Python Case Studies
  • Multiple Choice Questions
  • 📝 Practice Problems
Get in Touch
  • tech2dsm@gmail.com

© Sankalan Data Tech

Python Language Interactive Tutorial

Python: Inheritance

Python Inheritance - Complete Guide

Learn how inheritance lets you create class hierarchies and reuse code effectively.

Created by Sankalan Data Tech Team Verified
Data Engineers, Analysts, Scientists & Trainers
Created by experienced Python developers, data engineers, and data scientists to make programming easy through practical examples, real-world experience, and clear explanations.
On this page:
  • What is Inheritance?
  • Parent and Child Classes
  • Method Overriding
  • The super() Function
  • Types of Inheritance
  • Multiple Inheritance
  • Multilevel Inheritance
  • Best Practices
  • Try It Yourself
  • Quick Quiz
  • Frequently Asked Questions
Share this tutorial:
Twitter LinkedIn Facebook WhatsApp Reddit Telegram Email Copy Link
What You'll Learn Here
  • What is inheritance — creating class hierarchies
  • Parent and child classes — the relationship
  • Method overriding — customizing behavior
  • The super() function — calling parent methods
  • Types of inheritance — single, multiple, multilevel
  • Best practices — using inheritance effectively

What is Inheritance?

Inheritance is a fundamental concept in Object-Oriented Programming that allows a class to inherit attributes and methods from another class. It's like a family tree for your code — child classes inherit from parent classes, just like children inherit traits from their parents.

Think of inheritance like a recipe. You have a basic recipe for a cake. Then you have a special recipe for a chocolate cake that uses the same basic steps but adds chocolate. The chocolate cake inherits from the basic cake.

In Python, inheritance lets you create a hierarchy of classes. The class that provides the attributes and methods is called the parent class (or base class). The class that inherits is called the child class (or derived class).

💡 Key concept: Inheritance is a way to create a new class using an existing class as a starting point. It promotes code reuse and helps organize related classes in a hierarchy.

Parent and Child Classes

1

Creating a Class Hierarchy

To create inheritance, you define a child class that inherits from a parent class. The child class automatically gets all the methods and attributes of the parent class. You can then add new methods or override existing ones.

# Parent and Child Classes

# Parent class (Base class)
class Animal:
    """A class representing an animal"""
    
    def __init__(self, name, species):
        self.name = name
        self.species = species
        self.is_alive = True
    
    def eat(self):
        return f"{self.name} is eating"
    
    def sleep(self):
        return f"{self.name} is sleeping"
    
    def get_info(self):
        return f"{self.name} is a {self.species}"

# Child class (Derived class) that inherits from Animal
class Dog(Animal):
    """A class representing a dog, inherits from Animal"""
    
    def __init__(self, name, breed):
        # Call the parent class's __init__ method
        super().__init__(name, "Dog")
        self.breed = breed
    
    def bark(self):
        return f"{self.name} says Woof!"
    
    def fetch(self):
        return f"{self.name} is fetching the ball"

# Child class (Derived class) that inherits from Animal
class Cat(Animal):
    """A class representing a cat, inherits from Animal"""
    
    def __init__(self, name, color):
        super().__init__(name, "Cat")
        self.color = color
    
    def meow(self):
        return f"{self.name} says Meow!"
    
    def purr(self):
        return f"{self.name} is purring"

# Creating objects from child classes
dog = Dog("Buddy", "Golden Retriever")
cat = Cat("Whiskers", "Orange")

# Using methods from the parent class
print(dog.get_info())  # Buddy is a Dog
print(cat.get_info())  # Whiskers is a Cat

print(dog.eat())  # Buddy is eating
print(cat.sleep())  # Whiskers is sleeping

# Using methods from the child classes
print(dog.bark())  # Buddy says Woof!
print(dog.fetch())  # Buddy is fetching the ball

print(cat.meow())  # Whiskers says Meow!
print(cat.purr())  # Whiskers is purring
                                

Parent and child classes key points:

  • Parent class — the class being inherited from
  • Child class — the class that inherits
  • Inheritance syntax — class Child(Parent):
  • All parent methods — child classes get all parent methods
  • Can add new methods — child classes can add new functionality
  • Can override methods — child classes can change parent methods

Quick Check: What is the relationship between a parent and child class? (Answer: The child class inherits from the parent class)

Method Overriding

2

Customizing Behavior in Child Classes

Method overriding is when a child class provides its own implementation of a method that is already defined in the parent class. This allows child classes to have specialized behavior while still maintaining a common interface.

# Method Overriding

class Vehicle:
    """A class representing a vehicle"""
    
    def __init__(self, make, model, year):
        self.make = make
        self.model = model
        self.year = year
    
    def start(self):
        return "Starting the vehicle"
    
    def stop(self):
        return "Stopping the vehicle"
    
    def get_info(self):
        return f"{self.year} {self.make} {self.model}"

class Car(Vehicle):
    """A class representing a car, overriding some methods"""
    
    def __init__(self, make, model, year, doors=4):
        super().__init__(make, model, year)
        self.doors = doors
    
    # Override the start method
    def start(self):
        return "Starting the car with a key"
    
    # Override the get_info method
    def get_info(self):
        return f"{self.year} {self.make} {self.model} with {self.doors} doors"

class Motorcycle(Vehicle):
    """A class representing a motorcycle, overriding some methods"""
    
    def __init__(self, make, model, year, has_sidecar=False):
        super().__init__(make, model, year)
        self.has_sidecar = has_sidecar
    
    # Override the start method
    def start(self):
        return "Starting the motorcycle with a kick-start"
    
    # Override the get_info method
    def get_info(self):
        sidecar = "with sidecar" if self.has_sidecar else "without sidecar"
        return f"{self.year} {self.make} {self.model} {sidecar}"

# Creating objects
car = Car("Toyota", "Camry", 2022)
bike = Motorcycle("Harley", "Sportster", 2021)

# Using overridden methods
print(car.start())  # Starting the car with a key
print(bike.start())  # Starting the motorcycle with a kick-start

# Using overridden get_info
print(car.get_info())  # 2022 Toyota Camry with 4 doors
print(bike.get_info())  # 2021 Harley Sportster without sidecar

# Parent methods can still be called using super()
class ElectricCar(Car):
    def __init__(self, make, model, year, doors=4, battery_range=300):
        super().__init__(make, model, year, doors)
        self.battery_range = battery_range
    
    def start(self):
        # Call parent method and add more
        parent_start = super().start()
        return f"{parent_start} silently"
    
    def get_info(self):
        return f"{super().get_info()} with {self.battery_range} mile range"

tesla = ElectricCar("Tesla", "Model 3", 2023, 4, 350)
print(tesla.start())  # Starting the car with a key silently
print(tesla.get_info())  # 2023 Tesla Model 3 with 4 doors with 350 mile range
                                

Method overriding key points:

  • Same name — overriding method has the same name as the parent
  • Different implementation — child class provides its own version
  • Parent method still exists — can be called using super()
  • Signature should match — parameters and return type
  • Used for specialization — customizing behavior for specific types

Quick Check: What is method overriding? (Answer: When a child class provides its own implementation of a parent method)

The super() Function

3

Calling Methods from the Parent Class

The super() function is used to call methods from the parent class. It's especially useful when you want to extend or customize the parent's behavior while still using its functionality.

# Using super() to call parent methods

class Employee:
    """A class representing an employee"""
    
    def __init__(self, name, employee_id):
        self.name = name
        self.employee_id = employee_id
        self.position = "Employee"
    
    def work(self):
        return f"{self.name} is working"
    
    def get_info(self):
        return f"{self.name} (ID: {self.employee_id}) - {self.position}"

class Manager(Employee):
    """A class representing a manager"""
    
    def __init__(self, name, employee_id, team_size):
        # Call parent __init__ using super()
        super().__init__(name, employee_id)
        self.position = "Manager"
        self.team_size = team_size
    
    def work(self):
        # Call parent work method and add more
        parent_work = super().work()
        return f"{parent_work} and managing {self.team_size} people"
    
    def get_info(self):
        # Use parent get_info and add more
        return f"{super().get_info()} with team of {self.team_size}"

class Developer(Employee):
    """A class representing a developer"""
    
    def __init__(self, name, employee_id, programming_language):
        super().__init__(name, employee_id)
        self.position = "Developer"
        self.programming_language = programming_language
    
    def work(self):
        parent_work = super().work()
        return f"{parent_work} in {self.programming_language}"
    
    def code(self):
        return f"{self.name} is writing {self.programming_language} code"

# Using the classes
manager = Manager("Alice", "M001", 5)
developer = Developer("Bob", "D001", "Python")

print(manager.work())  # Alice is working and managing 5 people
print(developer.work())  # Bob is working in Python

print(manager.get_info())  # Alice (ID: M001) - Manager with team of 5
print(developer.get_info())  # Bob (ID: D001) - Developer

print(developer.code())  # Bob is writing Python code

# super() in multiple inheritance
class LoggingMixin:
    def log(self, message):
        print(f"LOG: {message}")

class Database:
    def save(self):
        print("Saving to database")

class User(LoggingMixin, Database):
    def save(self):
        super().log("Saving user...")
        super().save()
        print("User saved successfully")

user = User()
user.save()
# LOG: Saving user...
# Saving to database
# User saved successfully
                                

super() key points:

  • Calls parent methods — allows you to use parent class functionality
  • Used in __init__ — to initialize parent attributes
  • Used in method overriding — to extend parent methods
  • Works in multiple inheritance — follows MRO (Method Resolution Order)
  • Makes code maintainable — changes to parent class propagate automatically

Quick Check: What does super() do? (Answer: It calls methods from the parent class)

Types of Inheritance

4

Different Inheritance Patterns

Python supports several types of inheritance patterns. Each pattern serves a different purpose and is useful in different situations. Let's look at the main types.

# Types of Inheritance

# 1. Single Inheritance
# A child class inherits from one parent class

class Animal:
    def __init__(self, name):
        self.name = name
    
    def eat(self):
        return f"{self.name} is eating"

class Dog(Animal):
    def bark(self):
        return f"{self.name} says Woof!"

# 2. Multiple Inheritance
# A child class inherits from multiple parent classes

class Flyable:
    def fly(self):
        return "Flying"

class Swimmable:
    def swim(self):
        return "Swimming"

class Duck(Flyable, Swimmable):
    def __init__(self, name):
        self.name = name
    
    def quack(self):
        return f"{self.name} says Quack!"

# 3. Multilevel Inheritance
# A child class inherits from another child class

class Animal:
    def __init__(self, name):
        self.name = name

class Mammal(Animal):
    def feed_milk(self):
        return f"{self.name} is feeding milk"

class Dog(Mammal):
    def bark(self):
        return f"{self.name} says Woof!"

# 4. Hierarchical Inheritance
# Multiple child classes inherit from a single parent class

class Shape:
    def area(self):
        pass

class Circle(Shape):
    def __init__(self, radius):
        self.radius = radius
    
    def area(self):
        return 3.14159 * self.radius ** 2

class Rectangle(Shape):
    def __init__(self, width, height):
        self.width = width
        self.height = height
    
    def area(self):
        return self.width * self.height

# 5. Hybrid Inheritance
# A combination of multiple and multilevel inheritance

class A:
    pass

class B(A):
    pass

class C(A):
    pass

class D(B, C):
    pass

# Demonstration
print("=== Single Inheritance ===")
dog = Dog("Buddy")
print(dog.eat())  # Buddy is eating
print(dog.bark())  # Buddy says Woof!

print("\n=== Multiple Inheritance ===")
duck = Duck("Donald")
print(duck.fly())  # Flying
print(duck.swim())  # Swimming
print(duck.quack())  # Donald says Quack!

print("\n=== Multilevel Inheritance ===")
dog2 = Dog("Max")
print(dog2.feed_milk())  # Max is feeding milk
print(dog2.bark())  # Max says Woof!

print("\n=== Hierarchical Inheritance ===")
circle = Circle(5)
rect = Rectangle(4, 6)
print(f"Circle area: {circle.area():.2f}")  # 78.54
print(f"Rectangle area: {rect.area()}")  # 24
                                

Types of inheritance:

  • Single — one parent, one child
  • Multiple — child inherits from multiple parents
  • Multilevel — chain of inheritance (grandparent → parent → child)
  • Hierarchical — multiple children from one parent
  • Hybrid — combination of multiple and multilevel

Quick Check: What is the difference between multiple and multilevel inheritance? (Answer: Multiple inheritance has one child with multiple parents; multilevel inheritance has a chain of parent-child relationships)

Multiple Inheritance

5

Inheriting from Multiple Parents

Multiple inheritance is a feature where a class can inherit from more than one parent class. This allows a class to combine the functionality of multiple classes. However, it also introduces complexity, especially when parent classes have methods with the same name.

# Multiple Inheritance in detail

# Example: A multimedia player

class AudioPlayer:
    def __init__(self):
        self.volume = 50
    
    def play_audio(self, file):
        return f"Playing audio: {file}"
    
    def adjust_volume(self, level):
        self.volume = level
        return f"Volume set to {level}"

class VideoPlayer:
    def __init__(self):
        self.brightness = 70
    
    def play_video(self, file):
        return f"Playing video: {file}"
    
    def adjust_brightness(self, level):
        self.brightness = level
        return f"Brightness set to {level}"

class MediaPlayer(AudioPlayer, VideoPlayer):
    def __init__(self):
        # Call parent constructors
        AudioPlayer.__init__(self)
        VideoPlayer.__init__(self)
        self.current_file = None
    
    def play(self, file):
        self.current_file = file
        if file.endswith(('.mp3', '.wav')):
            return self.play_audio(file)
        elif file.endswith(('.mp4', '.avi')):
            return self.play_video(file)
        else:
            return "Unsupported file format"

# Using the MediaPlayer
player = MediaPlayer()
print(player.play("song.mp3"))  # Playing audio: song.mp3
print(player.play("movie.mp4"))  # Playing video: movie.mp4
print(player.adjust_volume(75))  # Volume set to 75
print(player.adjust_brightness(80))  # Brightness set to 80

# Example: A smart device

class SmartDevice:
    def __init__(self):
        self.is_on = False
    
    def turn_on(self):
        self.is_on = True
        return "Device turned on"
    
    def turn_off(self):
        self.is_on = False
        return "Device turned off"

class Camera:
    def take_photo(self):
        return "Photo taken"
    
    def record_video(self):
        return "Video recording"

class Phone(SmartDevice, Camera):
    def __init__(self):
        SmartDevice.__init__(self)
        self.battery = 100
    
    def make_call(self, number):
        return f"Calling {number}"
    
    def charge(self):
        self.battery = 100
        return "Phone charged"

phone = Phone()
print(phone.turn_on())  # Device turned on
print(phone.take_photo())  # Photo taken
print(phone.make_call("123-456-7890"))  # Calling 123-456-7890

# Method Resolution Order (MRO)
print("\nMRO for MediaPlayer:")
for cls in MediaPlayer.__mro__:
    print(f"  {cls.__name__}")
# MediaPlayer → AudioPlayer → VideoPlayer → object
                                

Multiple inheritance key points:

  • Multiple parents — child inherits from two or more classes
  • Combines functionality — gets methods from all parents
  • Method Resolution Order (MRO) — determines which parent method is called first
  • Constructor calls — need to call each parent's __init__
  • Use with caution — can lead to complexity and confusion

Quick Check: What is MRO in multiple inheritance? (Answer: Method Resolution Order — the order in which parent classes are searched for methods)

Multilevel Inheritance

6

Chain of Inheritance

Multilevel inheritance is when a class inherits from another class, which in turn inherits from another class. This creates a chain of inheritance, where each level adds more specific functionality.

# Multilevel Inheritance

class Animal:
    """Base class"""
    def __init__(self, name):
        self.name = name
    
    def eat(self):
        return f"{self.name} is eating"
    
    def sleep(self):
        return f"{self.name} is sleeping"

class Mammal(Animal):
    """Inherits from Animal"""
    def __init__(self, name, fur_color):
        super().__init__(name)
        self.fur_color = fur_color
    
    def feed_milk(self):
        return f"{self.name} is feeding milk"
    
    def warm_blooded(self):
        return True

class Dog(Mammal):
    """Inherits from Mammal"""
    def __init__(self, name, fur_color, breed):
        super().__init__(name, fur_color)
        self.breed = breed
    
    def bark(self):
        return f"{self.name} says Woof!"
    
    def fetch(self):
        return f"{self.name} is fetching"

class Puppy(Dog):
    """Inherits from Dog"""
    def __init__(self, name, fur_color, breed, age):
        super().__init__(name, fur_color, breed)
        self.age = age
    
    def play(self):
        return f"{self.name} is playing"
    
    def bark(self):
        # Override bark method
        return f"{self.name} says Yip Yip!"

# Creating a Puppy object
puppy = Puppy("Max", "Golden", "Golden Retriever", 3)

# Methods from Animal
print(puppy.eat())  # Max is eating
print(puppy.sleep())  # Max is sleeping

# Methods from Mammal
print(puppy.feed_milk())  # Max is feeding milk
print(f"Warm blooded: {puppy.warm_blooded()}")  # True

# Methods from Dog
print(puppy.bark())  # Max says Yip Yip! (overridden)
print(puppy.fetch())  # Max is fetching

# Methods from Puppy
print(puppy.play())  # Max is playing

# Inheritance chain:
# Puppy → Dog → Mammal → Animal → object

# Checking the inheritance chain
print(f"Is Puppy a Dog? {isinstance(puppy, Dog)}")  # True
print(f"Is Puppy a Mammal? {isinstance(puppy, Mammal)}")  # True
print(f"Is Puppy an Animal? {isinstance(puppy, Animal)}")  # True
print(f"Is Dog a Mammal? {issubclass(Dog, Mammal)}")  # True
                                

Multilevel inheritance key points:

  • Chain of inheritance — classes form a hierarchy
  • Each level adds — more specific functionality
  • Inherits from ancestors — gets methods from all parent classes
  • Method overriding — each level can override methods
  • Isinstance and issubclass — check inheritance relationships

Quick Check: What is multilevel inheritance? (Answer: A chain of inheritance where a class inherits from another class that inherits from another class)

Best Practices for Inheritance

7

Using Inheritance Effectively

# Best practices for inheritance

# 1. Use inheritance for "is-a" relationships
#  Good: Dog IS-A Animal
class Animal: pass
class Dog(Animal): pass

#  Bad: Car IS-A Engine (should be composition)
# class Car(Engine): pass  # Wrong relationship

# 2. Keep the hierarchy shallow
#  Good: 2-3 levels deep
class Animal: pass
class Mammal(Animal): pass
class Dog(Mammal): pass

#  Bad: Very deep hierarchy (5+ levels)
# class A: pass
# class B(A): pass
# class C(B): pass
# class D(C): pass
# class E(D): pass

# 3. Use super() to call parent methods
class Parent:
    def __init__(self, name):
        self.name = name

class Child(Parent):
    def __init__(self, name, age):
        super().__init__(name)  #  Good
        self.age = age

#  Bad: Hardcoding parent name
# class Child(Parent):
#     def __init__(self, name, age):
#         Parent.__init__(self, name)  # Hardcoded

# 4. Follow the Liskov Substitution Principle
# Subclasses should be substitutable for their parent classes
class Rectangle:
    def __init__(self, width, height):
        self.width = width
        self.height = height

class Square(Rectangle):
    def __init__(self, side):
        super().__init__(side, side)
    
    #  Good: Square IS-A Rectangle
    # Square can be used wherever Rectangle is expected

# 5. Use composition when inheritance doesn't fit
#  Composition: A class uses another class
class Engine:
    def start(self):
        return "Engine started"

class Car:
    def __init__(self):
        self.engine = Engine()  # Composition
    
    def start(self):
        return self.engine.start()

# 6. Document inheritance relationships
class Employee:
    """
    Base class for all employees.
    
    Subclasses:
        Manager: Manages teams
        Developer: Writes code
        Designer: Creates designs
    """
    pass

# 7. Keep classes focused
# Each class should have a single responsibility
class DataProcessor:
    """Only processes data"""
    pass

class DataValidator:
    """Only validates data"""
    pass

#  Bad: One class does everything
class DataManager:
    """Processes, validates, and stores data"""
    pass
                                

Best practices summary:

  • Is-a relationships — inheritance for "is-a" relationships
  • Keep hierarchies shallow — avoid deep inheritance chains
  • Use super() — for calling parent methods
  • Liskov Substitution — subclasses should be substitutable
  • Prefer composition — when inheritance doesn't fit
  • Document relationships — explain inheritance hierarchies

Quick Check: What is the Liskov Substitution Principle? (Answer: Subclasses should be substitutable for their parent classes)

Try It Yourself

Experiment with inheritance in the editor below.

Loading Pyodide... 0%
Python Code Editor
========================================
INHERITANCE PRACTICE
========================================

1. BASIC INHERITANCE
Hi, I'm Alice, 20 years old
Alice is studying

2. METHOD OVERRIDING
Dog: Woof!
Cat: Meow!

3. USING SUPER()
Vehicle starting car

Inheritance practice complete!
🏆

You've Got It!

You now understand inheritance in Python. You know how to create parent and child classes, override methods, use super(), and work with different inheritance patterns.

Quick Quiz

Test what you've learned:

1. What is inheritance?
2. What is the syntax for a child class inheriting from a parent class?
3. What is method overriding?
4. What does super() do?
5. What is the difference between single and multiple inheritance?

Frequently Asked Questions

What is the difference between inheritance and composition? ▼

Inheritance is an "is-a" relationship (e.g., Dog is an Animal). Composition is a "has-a" relationship (e.g., Car has an Engine). Inheritance creates a parent-child relationship; composition uses objects as attributes. Both are valid approaches; choose based on the relationship between classes.

What is the Method Resolution Order (MRO)? ▼

MRO is the order in which Python searches for methods in a class hierarchy. In multiple inheritance, it determines which parent class's method is called first. You can check the MRO using the __mro__ attribute or the mro() method.

What is the Liskov Substitution Principle? ▼

The Liskov Substitution Principle states that objects of a subclass should be substitutable for objects of the parent class without affecting the correctness of the program. In other words, child classes should be able to stand in for parent classes.

What's a common interview question about inheritance? ▼

Common questions include: "What is the difference between inheritance and composition?" "Explain method overriding with an example" "What is multiple inheritance and what are its challenges?" and "What is the purpose of super()?"

Can a child class have multiple parents? ▼

Yes, Python supports multiple inheritance, where a child class can inherit from more than one parent class. This allows the child class to combine functionality from multiple parents. However, it can lead to complexity and should be used carefully.

What happens if a child class doesn't override a method? ▼

If a child class doesn't override a method, it inherits the parent class's method as-is. The child class can use the method without any modification. This is the default behavior and is what makes inheritance useful for code reuse.

Where to Go From Here

Now that you understand inheritance, check out these related topics:

Single Inheritance

Learn more about single inheritance in detail.

Learn More →

Multiple Inheritance

Learn about multiple inheritance and the diamond problem.

Learn More →

Method Overriding

Learn more about overriding methods in subclasses.

Learn More →
Interview Resources
  • Python Syntax & Variables Interview Questions
  • Top SQL Interview Questions & Answers
  • SQL Joins: Displaying Data from Multiple Tables FAQ
  • Python Lists and Dictionaries Interview Questions
  • Python OOP Interview Questions
  • SQL Set Operators Interview Questions
Previous: Class and Instance Variables Next: Single Inheritance →