🎓 A1Learner
🔍
0 of 102 lessons completed

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?