Python Multiple Inheritance and Method Resolution Order
Learn how Python combines multiple base classes, resolves inherited attributes with the method resolution order, and uses super() cooperatively across a multiple-inheritance hierarchy.
Intermediate
Python classes can inherit from more than one base class. Multiple inheritance is not just a list of parents: Python uses a method resolution order (MRO) to decide which class is searched first and how cooperative super() calls continue through the hierarchy.
Define a class with multiple base classes
A class can list two or more base classes. The new class can use behavior supplied by each base, as long as the inherited names can be resolved consistently.
|
|
Duck combines the two independent behaviors inherited from Flyer and Swimmer.
The order of the bases affects method lookup
When multiple bases provide the same attribute, Python needs a defined search order. The left-to-right base order contributes to that order, so changing the bases can change which inherited implementation is found first.
|
|
EmailSender appears before FileSender, so its send() implementation is found first for Notification.
Inspect the complete method resolution order
Every class has a __mro__ tuple containing the classes considered during method resolution. Reading it is useful when you need to explain or debug inherited behavior.
|
|
The MRO begins with C and then lists the classes Python searches for inherited attributes.
__bases__ and __mro__ show different views
__bases__ contains only the direct base classes from the class definition. __mro__ contains the complete method-resolution search order, including indirect bases and object when applicable.
|
|
__bases__ shows only C's direct base B, while __mro__ shows the complete lookup path through C, B, A, and object.
Python uses C3 method resolution order
Python uses the C3 method resolution order. It preserves the local left-to-right ordering of bases, keeps a class from being visited twice in a diamond hierarchy, and produces a consistent linear search path.
|
|
Root is included once in Bottom's MRO even though Bottom reaches it through both Left and Right.
A diamond hierarchy can cooperate through super()
In cooperative multiple inheritance, super() means continue with the next class in the MRO. Each class can perform its own work and then delegate, allowing the whole chain to participate exactly once.
|
|
The cooperative calls follow Bottom, Left, Right, then Root—the same order shown by Bottom.__mro__.
super() is not simply a call to one named parent
A direct call such as Parent.method(self) names one specific implementation. In a cooperative multiple-inheritance hierarchy, super() is different: it follows the MRO and can allow sibling branches to participate in the same chain.
|
|
super() moves through C, A, B, and Root instead of stopping after a single named parent.
Some inheritance combinations cannot produce an MRO
Not every combination of bases has a consistent linear order. When the ordering constraints conflict, Python raises TypeError while creating the class instead of choosing an arbitrary search path.
|
|
The conflicting requirements from First and Second make a consistent MRO impossible, so class creation raises TypeError.
Use multiple inheritance deliberately
Multiple inheritance is most useful when the participating classes have clearly compatible responsibilities and can cooperate through the MRO. Small, focused mixin-style bases can be useful. When behavior is unrelated or state coordination becomes confusing, composition or simpler inheritance may be clearer.
|
|
These two focused bases contribute independent behavior without competing over the same method name.
Key takeaways
- A class can have multiple direct bases, and their ordering contributes to method resolution.
- __bases__ shows direct bases, while __mro__ shows the complete method-resolution order.
- Python uses C3 method resolution order to produce a consistent search path and avoid duplicate visits to shared bases.
- In cooperative multiple inheritance, super() delegates to the next class in the MRO rather than one hard-coded parent.
- Conflicting inheritance constraints cause TypeError during class creation instead of an ambiguous MRO.
Thanks for your feedback.
Mark this learning resource complete to track your learning progress.