In the journey of mastering Python, understanding Inheritance is a pivotal step that opens the door to creating more modular, reusable, and manageable code. Inheritance is a fundamental concept in object-oriented programming (OOP) that allows one class to inherit attributes and methods from another, facilitating code reuse and establishing a natural hierarchy between classes.
Imagine you're designing a software system for a zoo. You have a general class called Animal, but you also want specific animals like Lion or Elephant to have their own unique features while still sharing common characteristics. How do you avoid rewriting the same code for every animal? This is precisely where inheritance shines.

What Is Inheritance in Python?
Inheritance allows a new class (called a child class or subclass) to acquire the properties and behaviors (attributes and methods) of an existing class (called the parent class or superclass). This means the subclass can:
- Use the fields and methods of the superclass without rewriting them.
- Override or extend the superclass's methods to provide specific behavior.
- Introduce new attributes and methods unique to the subclass.
This makes your code more DRY (Don't Repeat Yourself) and easier to maintain.
Basic Syntax of Inheritance
In Python, inheritance is declared by placing the parent class name in parentheses after the child class name:
class ParentClass:
# parent class code
class ChildClass(ParentClass):
# child class code
Let's see a straightforward example.
📌 Deep Dive: Simple Inheritance Example
class Animal:
def __init__(self, name):
self.name = name
def speak(self):
return f"{self.name} makes a sound."
class Dog(Animal):
def speak(self):
return f"{self.name} barks."
dog = Dog("Buddy")
print(dog.speak())
Here, Dog inherits from Animal and overrides the speak method to provide a behavior specific to dogs. The Dog class automatically has access to the __init__ method of Animal, so we don't have to rewrite it.
Why Use Inheritance?
Inheritance provides several key advantages:
- Code Reusability: Share common code among related classes.
- Extensibility: Easily extend or modify behavior without changing the original class.
- Logical Hierarchy: Model real-world relationships, such as “is-a” relationships (a dog is an animal).
- Maintenance: Fix or improve functionality in the base class and have it reflected in all subclasses.
💡 Analogy: Family Traits
Think of a parent passing down certain traits to their children—eye color, height, or talents. Similarly, in programming, a parent class passes down attributes and methods to its child classes.
Overriding Methods: Customizing Behavior
A subclass can provide its own version of a method defined in its superclass, a process called method overriding. This allows the subclass to modify or extend the behavior inherited from the parent.
In the previous example, the Dog class overrides the speak method inherited from Animal. If a method is not overridden, the subclass will use the parent class's version.
Using super() to Access Parent Methods
Sometimes, you want to extend the behavior of a parent class method rather than completely replacing it. The built-in super() function helps you call the parent class’s method inside the overridden method.
📌 Deep Dive: Using super() in Inheritance
class Animal:
def __init__(self, name):
self.name = name
def speak(self):
return f"{self.name} makes a sound."
class Cat(Animal):
def __init__(self, name, color):
super().__init__(name) # Call the parent's __init__
self.color = color
def speak(self):
base_speak = super().speak() # Call the parent's speak
return base_speak + f" Specifically, {self.name} meows."
cat = Cat("Whiskers", "black")
print(cat.speak())
Here, Cat calls the __init__ method of Animal to set the name, then adds its own color attribute. The speak method calls the parent’s speak and extends its output.
Types of Inheritance in Python
Inheritance can take several forms depending on how classes relate:
- Single Inheritance: Child inherits from a single parent class.
- Multiple Inheritance: Child inherits from more than one parent class.
- Multilevel Inheritance: A chain where a subclass inherits from a class that is itself a subclass.
- Hierarchical Inheritance: Multiple subclasses inherit from one parent class.
- Hybrid Inheritance: Combination of two or more types of inheritance.
| Inheritance Type | Description |
|---|---|
| Single | One child inherits from one parent. |
| Multiple | One child inherits from multiple parents. |
| Multilevel | Inheritance chain with multiple generations. |
| Hierarchical | Multiple children inherit from one parent. |
| Hybrid | Combination of above types. |
Multiple Inheritance Example
Python supports multiple inheritance, allowing a class to inherit from multiple parent classes. This can be powerful but also requires careful design to avoid complications like the "diamond problem."
📌 Deep Dive: Multiple Inheritance
class Flyer:
def fly(self):
return "I can fly!"
class Swimmer:
def swim(self):
return "I can swim!"
class Duck(Flyer, Swimmer):
def quack(self):
return "Quack!"
donald = Duck()
print(donald.fly())
print(donald.swim())
print(donald.quack())
Here, Duck inherits behaviors from both Flyer and Swimmer, illustrating multiple inheritance.
⚠️ Caution with Multiple Inheritance
Multiple inheritance can lead to complex situations, especially when parent classes have methods with the same name. Python uses the Method Resolution Order (MRO) to determine which method to use, but it’s best to design your class hierarchy carefully to avoid confusion.
The Method Resolution Order (MRO)
When a method or attribute is accessed, Python follows the MRO to decide which class's method to invoke. You can see the MRO of a class using the __mro__ attribute or the mro() method:
📌 Deep Dive: Inspecting MRO
class A:
pass
class B(A):
pass
class C(B):
pass
print(C.__mro__)
print(C.mro())
In this example, Python looks for methods starting in class C, then B, then A, and finally the base object class.
Inheritance and Constructors
When a subclass defines its own __init__ constructor, the parent’s constructor is not called automatically. If you want to initialize the parent class’s attributes, you must explicitly call the parent's __init__ method, usually via super().
💡 Remember
Always call super().__init__() in your subclass constructor if you want to initialize the parent class properly.
Practical Example: Vehicle Inheritance Hierarchy
Let's create a small inheritance hierarchy for vehicles to see inheritance in action in a more applied context.
📌 Deep Dive: Vehicle Classes with Inheritance
class Vehicle:
def __init__(self, make, model):
self.make = make
self.model = model
def drive(self):
return f"The {self.make} {self.model} is driving."
class Car(Vehicle):
def drive(self):
return f"The car {self.make} {self.model} cruises on the road."
class Boat(Vehicle):
def drive(self):
return f"The boat {self.make} {self.model} sails on the water."
class AmphibiousVehicle(Car, Boat):
def drive(self):
car_drive = super(Car, self).drive() # Call Boat's drive
return car_drive + " Also, it can drive on land."
# Creating instances
car = Car("Toyota", "Corolla")
boat = Boat("Yamaha", "242X")
amphi = AmphibiousVehicle("Gibbs", "Amphitruck")
print(car.drive())
print(boat.drive())
print(amphi.drive())
In this example, AmphibiousVehicle inherits from both Car and Boat. We use super() with arguments to call Boat's drive method explicitly, then add extra functionality.
Key Points to Remember
- Inheritance defines an “is-a” relationship: a subclass is a type of the superclass.
- Child classes inherit all attributes and methods from the parent class.
- Method overriding allows subclasses to define their own behavior.
super()helps call parent class methods in subclasses.- Multiple inheritance is possible but should be used carefully.
- Python’s MRO defines method lookup order in complex hierarchies.
When Not to Use Inheritance
While inheritance is powerful, sometimes composition or delegation might be better choices:
- If two classes do not share an “is-a” relationship, avoid inheritance.
- Inheritance can increase coupling, making changes harder if your hierarchy grows complex.
- Favor composition (has-a relationships) when behavior sharing is better done by including objects rather than inheriting.
💡 Tip: Use inheritance to model natural hierarchies and shared behavior, but don’t hesitate to use composition for more flexible designs.
Summary
Inheritance is a cornerstone of Python’s object-oriented programming paradigm. It helps you write cleaner, more reusable code by allowing classes to inherit from other classes. Understanding how to inherit, override, and extend behavior with super() empowers you to design scalable and maintainable applications.
As you practice inheritance, remember to balance it with other design principles and keep your class hierarchies logical and intuitive.
Quick Knowledge Check
Test what you just learned
Question 1 of 2
What keyword do you use in Python to refer to the parent class inside a subclass?
Question 2 of 2
If a subclass does not override a method inherited from its parent, what happens when you call that method on an instance of the subclass?
Loading results...