Method Resolution Order
For old classes (in Python 2 only) it was vertical-then-horizontal order of looking up for object attributes/methods.
For Python 3.x and for New style classes (Python 2.5+) MRO is horizontal-then-vertical order.
Old style class MRO
Just for information as it is used only in Python 2! It is helpful to understand how MRO works now though.
So as you can see value of C.x is ignored even if it is "closer". This was completely redesigned.
The old MRO builds a list of classes to search for methods. This algorithm is a tree routing:
Deep first, from left to right
Look if method exists in instance class
If not, looks if it exists in its first parent, then in the parent of the parent and so on
If not, it looks if current class inherits from others classes up to the current instance others parents.
New style class MRO
The problem with old style classes is that if we going to inherit from base object
we wouldn't be able to change anything. All because the logic of searching was too simple and wasn't designed for the case where everything is inherited from object
.
🪄 Code:
📟 Output:
Difference to old MRO is the additional check done each time before adding some class to the search path. The check is:
Is this class is the parent for some other class in the search path that will be added soon?
If yes → then it is been shifted after it's inherited class in order to not shadow it's methods.
This new algorithm (used by default in Python 3 and in Python 2 - from 2.2 when subclassing object
) is called C3-linearization in case of multiple inheritance to build an order of inheritance hierarchy in which it will search for matching method/attribute.
It can be described in one sentence as:
Deep first, from left to right with additional check and shifting the class that is parent for next classes after them.
The result of MRO linearization is stored in attribute __mro__
.
🪄 Code:
📟 Output:
So, Python 2 would build this MRO:
D, B, A, C, A
We see that A
is repeated, so removing first one keeping the last one will be Python 3's MRO:
D, B, C, A
🪄 Code:
📟 Output:
🪄 Code:
📟 Output:
What's important to know about C3 is that it guarantees three important features:
Subclasses appear before base classes
Base class declaration order is preserved
For all classes in an inheritance graph, the relative orderings guaranteed by 1 and 2 are preserved at all points in the graph.
Caveats
Sometimes the MRO can not be built:
Another example where object
is used before the class which inherites from it which confuses the logic:
🪄 Code:
📟 Output:
Last updated