Multiple Inheritance
Python supports inheriting from more than one base class.
Basic Syntax
class A:
def hello(self):
print("Hello from A")
class B:
def hello(self):
print("Hello from B")
class C(A, B): # inherits from both A and B
pass
c = C()
c.hello() # "Hello from A" — A comes first in MRO
MRO — Method Resolution Order
Python uses the C3 linearization algorithm to determine the order in which base classes are searched.
C.__mro__
# (<class 'C'>, <class 'A'>, <class 'B'>, <class 'object'>)
# Inspect at runtime
C.mro()
Rule of thumb: left-to-right, depth-first, no class appears before its subclass.
The Diamond Problem
class Base:
def method(self):
print("Base")
class Left(Base):
def method(self):
print("Left")
class Right(Base):
def method(self):
print("Right")
class Diamond(Left, Right):
pass
Diamond().method() # "Left"
Diamond.__mro__
# Diamond → Left → Right → Base → object
C3 linearization ensures Base appears only once.
super() and MRO
super() follows the MRO, not just the immediate parent. This is crucial in multiple inheritance.
class Base:
def method(self):
print("Base")
class Left(Base):
def method(self):
print("Left")
super().method() # calls Right.method (next in MRO)
class Right(Base):
def method(self):
print("Right")
super().method() # calls Base.method
class Diamond(Left, Right):
def method(self):
print("Diamond")
super().method()
Diamond().method()
# Diamond → Left → Right → Base
Mixins Pattern
A mixin is a class designed to add a specific, reusable behavior without being instantiated directly.
class JsonMixin:
def to_json(self):
import json
return json.dumps(self.__dict__)
class LogMixin:
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("Alice", "alice@example.com")
u.to_json() # '{"name": "Alice", "email": "alice@example.com"}'
u.log()
Key Interview Points
- Python resolves method calls using MRO (C3 linearization) — always left-to-right, breadth-first variant.
ClassName.__mro__orClassName.mro()shows the resolution order.super()walks the MRO, not just the direct parent — essential for cooperative multiple inheritance.- Mixins are the recommended pattern: small, focused classes that each add one behavior; main class inherits from several.
- A mixin should not define
__init__(or callsuper().__init__()cooperatively) and should not be instantiated directly. - Avoid deep or wide inheritance hierarchies — prefer composition over inheritance when possible.