Python Inheritance
What is Inheritance?
Inheritance allows one class to reuse the functionality of another class. Instead of duplicating code across related classes, shared logic lives in one place — making it easier to maintain and modify.
class Employee(Person): # Employee inherits from Person
pass
Terminology
| Term | Meaning |
|---|---|
| Child / Subclass / Derived class | The class that inherits (e.g. Employee) |
| Parent / Superclass / Base class | The class being inherited from (e.g. Person) |
The direction is one-way: the child gets access to the parent, but not vice versa.
Basic Example
class Person:
def __init__(self, first_name, last_name):
self.first_name = first_name
self.last_name = last_name
def say_hello(self):
print(f"Hi, my name is {self.first_name} {self.last_name}")
class Employee(Person):
pass # inherits everything from Person
e = Employee("Tim", "Programmer")
e.say_hello() # Hi, my name is Tim Programmer ✅
No __init__ needed in Employee — it uses Person's automatically.
Overriding Methods
Define a method with the same name in the child class to replace the parent's version:
class Employee(Person):
def say_hello(self):
print("---")
super().say_hello() # calls Person's say_hello
print("---")
super()gives access to the parent classsuper().say_hello()calls the parent's method on the current instance- Without
super(), the parent's version is completely replaced
Overriding __init__ (the Constructor)
When adding new attributes in a child class, override __init__ and call the parent's constructor with super():
class Employee(Person):
def __init__(self, first_name, last_name, salary):
super().__init__(first_name, last_name) # must call this!
self.salary = salary
⚠️ Always call
super().__init__()when overriding a constructor. The parent's__init__may set up attributes that its own methods depend on. Skipping it can cause errors later.
Inheritance Hierarchies
Classes can inherit across multiple levels:
class Person:
...
class Employee(Person): # Employee is a Person
...
class Manager(Employee): # Manager is an Employee AND a Person
def __init__(self, first_name, last_name, salary, department):
super().__init__(first_name, last_name, salary)
self.department = department
When super() is called in Manager, it refers to Employee — not Person directly.
The isinstance() Function
Checks if an object is an instance of a class (including parent classes):
m = Manager("Tim", "Programmer", 50000, "Sports")
isinstance(m, Manager) # True
isinstance(m, Employee) # True — Manager inherits from Employee
isinstance(m, Person) # True — Employee inherits from Person
isinstance(m, Owner) # False — no relation
The "Is-A" Rule
If a class inherits from another, every instance of the child must be an example of the parent.
class Manager(Employee): # ✅ Valid — every manager IS an employee
class Manager(Owner): # ❌ Invalid — not every manager IS an owner
Use this rule to decide whether inheritance is appropriate.
Polymorphism
Polymorphism (Greek: "many forms") means an object can be treated as different types depending on context.
- A
Managerinstance can be used as aManager, anEmployee, or aPerson - All share the same interface (e.g.
say_hello) but may behave differently if the method is overridden
Multiple Inheritance
Python allows a class to inherit from more than one parent:
class C(A, B):
pass
Method Resolution Order (MRO)
When a method is called, Python searches in this order:
1. The class itself (C)
2. First listed parent (A)
3. Second listed parent (B)
class A:
def __init__(self): print("A")
class B:
def __init__(self): print("B")
class C(A, B):
pass
C() # prints "A" — A is checked first
super() also follows MRO — it starts with the first parent and moves to the next only if the method isn't found.
⚠️ Multiple inheritance gets complex quickly. The is-a rule still applies to both parents. Use it sparingly.
Duck Typing
"If it walks like a duck and quacks like a duck, it must be a duck."
Python doesn't check whether an object has a method before running the code. It just tries it:
animals = [Duck(), Duck(), Whale()]
for animal in animals:
animal.swim()
animal.fly() # crashes only when Whale is reached — not before
- In languages like Java, the code wouldn't even compile — the type mismatch is caught early
- In Python, it runs until it fails at runtime
- This is duck typing: Python cares whether an object can do something, not what type it is
Key Takeaways & Recap
| Concept | Summary |
|---|---|
| Inheritance | Child class reuses parent class functionality |
super() |
Access the parent class; always call in overridden __init__ |
| Method override | Redefine a method in the child to change its behaviour |
isinstance() |
Checks type including inherited types |
| Is-A rule | Only inherit if every child instance truly "is a" parent |
| Polymorphism | One object, multiple usable forms depending on context |
| MRO | Left-to-right search order for methods in multiple inheritance |
| Duck typing | Python tries methods at runtime regardless of type |