Gyaan

Inheritance and MRO

intermediate inheritance MRO super diamond-problem

Inheritance lets a class borrow attributes and methods from another class. The parent is called the base class, and the child is the derived class. Think of it like genetics — a child inherits traits from their parents.

Single Inheritance

The simplest form. One child, one parent.

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

    def speak(self):
        return "..."

class Dog(Animal):  # Dog inherits from Animal
    def speak(self):
        return f"{self.name} says Woof!"

dog = Dog("Buddy")
print(dog.speak())  # Buddy says Woof!
print(dog.name)     # Buddy — inherited from Animal

super() — Calling the Parent

Instead of hardcoding the parent class name, we use super(). It gives us a reference to the parent so we can call its methods.

class Dog(Animal):
    def __init__(self, name, breed):
        super().__init__(name)  # call Animal's __init__
        self.breed = breed

Multiple Inheritance and the Diamond Problem

Python allows a class to inherit from multiple parents. This is powerful but can get confusing — especially with the diamond problem.

Diamond Inheritance — MRO Resolution
A
base class
/     \
B(A)
MRO #2
C(A)
MRO #3
\     /
D(B, C)
MRO #1 — starts here
MRO: D → B → C → A → object

The diamond problem: if both B and C inherit from A, and D inherits from both B and C — which version of A’s methods does D get?

C3 Linearization (MRO)

Python solves this with C3 linearization — an algorithm that creates a predictable method lookup order. We can inspect it:

class A:
    def who(self): return "A"

class B(A):
    def who(self): return "B"

class C(A):
    def who(self): return "C"

class D(B, C):
    pass

print(D().who())   # B — because B comes before C in MRO
print(D.mro())     # [D, B, C, A, object]

The rule is: Python checks the class itself first, then left-to-right through the parents, making sure a parent isn’t visited before all its children.

isinstance and issubclass

print(isinstance(D(), B))    # True — D is a child of B
print(isinstance(D(), A))    # True — D is also a child of A (transitive)
print(issubclass(D, A))      # True — the class D itself is a subclass of A

Mixins

A mixin is a small class meant to be combined with others via multiple inheritance. It adds a specific behavior without being a standalone class.

class JsonMixin:
    def to_json(self):
        import json
        return json.dumps(self.__dict__)

class User(JsonMixin):
    def __init__(self, name):
        self.name = name

print(User("Manish").to_json())  # {"name": "Manish"}

In simple language, inheritance lets us reuse code by building on existing classes. When multiple parents are involved, Python uses MRO (C3 linearization) to decide which method to call — always predictable, always left-to-right.