Python inheritance and method overriding
single inheritance, super() function, method overriding, isinstance, issubclass, multiple inheritance, MRO
Inheritance
Inheritance lets a child class reuse and extend a parent class. Use super() to call the parent's implementation.
class Animal:
def __init__(self, name):
self.name = name
def speak(self):
return "..."
class Dog(Animal):
def speak(self): # override
return f"{self.name}: Woof!"
class Cat(Animal):
def speak(self):
return f"{self.name}: Meow!"
animals = [Dog("Rex"), Cat("Luna")]
for a in animals:
print(a.speak()) # polymorphism
Calling super()
class Employee(Animal):
def __init__(self, name, role):
super().__init__(name) # call Animal.__init__
self.role = role
Checking Types
d = Dog("Rex")
print(isinstance(d, Dog)) # True
print(isinstance(d, Animal)) # True
print(issubclass(Dog, Animal))# True
Python supports multiple inheritance. When two parents have the same method, Python uses the MRO (C3 linearisation) to decide which runs first. Check it with ClassName.__mro__.
Inheritance expresses an 'is-a' relationship. Before reaching for inheritance, ask whether composition (an object holding a reference to another object) is a better fit — it is more flexible and avoids tight coupling. Python supports multiple inheritance, and the MRO ensures a consistent and predictable resolution order. The practical rule: use single inheritance by default, use mixins for adding specific capabilities (like serialisation or logging), and avoid deep inheritance chains deeper than three levels as they become difficult to reason about.
Always call super().__init__() early in a child class initialiser so parent attributes exist before you try to use them. Forgetting this causes AttributeError on the first attribute access. Python's MRO becomes important with mixins: a mixin is a small class that adds one focused capability and is designed to be mixed in alongside a main parent. Common mixin examples are LoggingMixin, JSONSerializableMixin, and TimestampMixin.
