Multiple Inheritance & the MRO

Understand the C3 linearisation that decides method lookup order — and how super() cooperates.

Python allows a class to inherit from several parents. When you call a method, Python must decide which parent's version to use. It follows the Method Resolution Order (MRO): a single, deterministic ordering of every ancestor, computed by the C3 linearisation algorithm.

Reading the MRO

Every class exposes its MRO. Python searches it left to right, top to bottom, and — crucially — never visits a class before all of its subclasses:

class A: pass
class B(A): pass
class C(A): pass
class D(B, C): pass

print([c.__name__ for c in D.__mro__])
# ['D', 'B', 'C', 'A', 'object']

super() follows the MRO, not the parent

The big surprise: super() does not mean "my parent class." It means "the next class in the MRO." In a diamond like the one above, super() inside B can land on C, not A. This is what makes cooperative multiple inheritance work — every class calls super() and the whole chain runs exactly once.

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • A mixin architecture uses super() correctly so that all mixins in the MRO chain are called in order.
  • A developer inspects ClassName.__mro__ to debug which class provides a method in a diamond hierarchy.
  • A framework uses the MRO to determine the correct order to apply multiple authentication mixins.

More examples

Inspect the MRO

Prints the C3-linearised MRO for a diamond hierarchy, showing the lookup order.

Example · python
class A: pass
class B(A): pass
class C(A): pass
class D(B, C): pass

print([cls.__name__ for cls in D.__mro__])
# ['D', 'B', 'C', 'A', 'object']

super() follows the MRO

Each super().hello() call follows the MRO, so all classes in the chain contribute their prefix.

Example · python
class A:
    def hello(self): return 'A'

class B(A):
    def hello(self): return 'B->' + super().hello()

class C(A):
    def hello(self): return 'C->' + super().hello()

class D(B, C):
    def hello(self): return 'D->' + super().hello()

print(D().hello())   # D->B->C->A

Mixin pattern with MRO

The LogMixin.save() logs and delegates to the next class in the MRO (Model) via super().

Example · python
class LogMixin:
    def save(self):
        print('Logging save')
        super().save()

class Model:
    def save(self): print('Saving to DB')

class LoggedModel(LogMixin, Model): pass

LoggedModel().save()
# Logging save
# Saving to DB

Discussion

  • Be the first to comment on this lesson.