Python Multiple Inheritance & MRO
Multiple inheritance is a class definition with two or more parents. The child gathers methods from every parent.
Two parents
Duck lists Flyer first, then Swimmer. Both parents define move.
class Flyer:
def move(self):
return "flies"
class Swimmer:
def move(self):
return "swims"
class Duck(Flyer, Swimmer):
pass
print(Duck().move())Read the order
The MRO shows the exact search order. The list ends with object.
class Flyer:
pass
class Swimmer:
pass
class Duck(Flyer, Swimmer):
pass
print([c.__name__ for c in Duck.__mro__])The diamond shape
Flying and Swimming share one parent. That shared parent forms a diamond shape.
class Animal:
pass
class Flying(Animal):
pass
class Swimming(Animal):
pass
class Duck(Flying, Swimming):
pass
print([c.__name__ for c in Duck.__mro__])Cooperative super
Each parent passes extra arguments along. The chain reaches every parent once.
class Animal:
def __init__(self, name, **kwargs):
super().__init__(**kwargs)
self.name = name
class Flying(Animal):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.can_fly = True
class Duck(Flying):
pass
duck = Duck(name="Daffy")
print(duck.name, duck.can_fly)A mixin adds one job
A mixin is small and focused. LogMixin only adds a label method.
class LogMixin:
def label(self):
return f"[{self.name}]"
class Named:
def __init__(self, name):
self.name = name
class Item(LogMixin, Named):
pass
print(Item("box").label())Example
class Animal:
def __init__(self, name, **kwargs):
super().__init__(**kwargs)
self.name = name
print(f"Animal ready: {self.name}")
class Flying(Animal):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.can_fly = True
print("Flying ready")
class Swimming(Animal):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.can_swim = True
print("Swimming ready")
class Duck(Flying, Swimming):
pass
print([c.__name__ for c in Duck.__mro__])
duck = Duck(name="Daisy")
print(duck.name, duck.can_fly, duck.can_swim)Key points
- Multiple inheritance: a class lists two or more parents in its brackets
- MRO: method resolution order, the list Python searches from left to right
- Use Class.__mro__ to see that order as a tuple of classes
- Use super() in every parent to keep a cooperative chain
- Mixin: a small parent class that adds one focused job
- C3: the rule Python uses to build a fair MRO from all parents
In this example, Animal stores the name. Flying and Swimming each extend Animal. Duck lists Flying first, then Swimming. The first print shows the MRO as class names. That order is Duck, Flying, Swimming, Animal, then object. Making a Duck starts the cooperative chain. Flying passes the call to Swimming with super(). Swimming passes the call to Animal with super(). Animal stores Daisy and prints first. Swimming prints next, then Flying prints last. The duck reports its name and both new flags.
Note
Python searches parents in the order you list them.
The first parent that has a method wins that search.
Try it Yourself
Edit the code, then press Run.
Running is simulated · Python Playground
Exercise
A class is written as class Duck(Flying, Swimming). Both parents define move(). Which move() does Duck use?