Course Progress75%
🍎 Python Advanced Python Topic 75 / 100
⏳ 8 min read

Multiple Inheritance

Inherit from multiple parent classes at once — how Python’s Method Resolution Order (MRO) decides which method wins.

"Multiple inheritance is powerful when used for small, focused mixins. The MRO is Python's promise: there will always be one clear, predictable order in which classes are searched."

— ShurAI

What is Multiple Inheritance?

A class can inherit from more than one parent at once. It gets all the attributes and methods from each parent:

python — basic multiple inheritance
class Flyable:
    def fly(self):
        print(f"{self.__class__.__name__} is flying")

class Swimmable:
    def swim(self):
        print(f"{self.__class__.__name__} is swimming")

class Duck(Flyable, Swimmable):   # inherits from both
    def quack(self):
        print("Quack!")

d = Duck()
d.fly()    # Duck is flying   — from Flyable
d.swim()   # Duck is swimming — from Swimmable
d.quack()  # Quack!           — Duck's own

The MRO — Method Resolution Order

When the same method exists in multiple parents, Python uses the MRO to decide which one wins. The MRO is the exact order Python searches classes for a method. Use .mro() or __mro__ to see it:

python
print(Duck.mro())
# [Duck, Flyable, Swimmable, object]

# Python searches left-to-right: Duck → Flyable → Swimmable → object
# First class in the MRO that has the method wins
MRO search order for Duck:
Duck
Flyable
Swimmable
object
Python stops at the first class that has the requested method and uses that version.

Conflict Resolution — Same Method in Both Parents

python
class A:
    def greet(self): print("Hello from A")

class B:
    def greet(self): print("Hello from B")

class C(A, B):   # A is listed first → A wins
    pass

class D(B, A):   # B is listed first → B wins
    pass

C().greet()   # Hello from A
D().greet()   # Hello from B
print(C.mro())  # [C, A, B, object]

Mixins — the Right Use of Multiple Inheritance

The most Pythonic pattern is mixins: small, focused classes that add one specific behaviour. They are designed to be combined:

python
class JsonMixin:
    """Mixin: add .to_json() to any class."""
    def to_json(self):
        import json
        return json.dumps(self.__dict__)

class LogMixin:
    """Mixin: add .log() to any class."""
    def log(self):
        print(f"[LOG] {self.__class__.__name__}: {self.__dict__}")

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

u = User("Riya", "riya@shurai.com")
u.log()          # [LOG] User: {'name': 'Riya', 'email': 'riya@shurai.com'}
print(u.to_json())  # {"name": "Riya", "email": "riya@shurai.com"}

super() Across the MRO Chain

python
class Base:
    def __init__(self): print("Base init")

class A(Base):
    def __init__(self):
        print("A init")
        super().__init__()   # calls next in MRO, not always Base!

class B(Base):
    def __init__(self):
        print("B init")
        super().__init__()

class C(A, B):
    def __init__(self):
        print("C init")
        super().__init__()

C()
# C init → A init → B init → Base init
# MRO: [C, A, B, Base, object]  — each super() goes to the next in line

"When in doubt, keep it simple: inherit from one main class and add mixins for extra capabilities. Deep diamond hierarchies are where bugs love to hide."

— ShurAI

🧠 Quiz — Q1

What does Python's MRO determine?

🧠 Quiz — Q2

Class C(A, B) and both A and B have a method greet(). Which version does C().greet() call?

🧠 Quiz — Q3

What is a mixin?

🧠 Quiz — Q4

How do you see the MRO of a class called Duck?