Demystifying
Python MRO
Amit Kumar | @aktech | me@iamit.in
v2.0
- SymPy Developer
- Mathematics and Computing undergrad
- Pythonista
- FOSS enthusiast!
I am ..
MRO
Method Resolution Order
defines the class search path used by Python to search for the right method to use in classes having multi-inheritance.
MRO?
class A:
def whoami(self):
print("I am A")
class B(A):
def whoami(self):
print("I am B")
class C(A, B):
pass
The Problem
object_c = C()
object_c.whoami()
?
Solution
Two algorithms to find Method Resolution Order
Old MRO
New MRO
Old Classes
New Classes
(C3 Algorithm)
Old Classes
class A :
pass
class B :
pass
class C(A, B) :
pass
New Classes
class A(object) :
pass
class B(object) :
pass
-
doesn't inherits from Python root object class.
- uses old mro algorithm
- first parent inherits from python root object class
- uses new mro algorithm
-
introduced in python 2.3
Lets Talk about MRO
(Brief History)
How it all Started?
2002
It all started in
with a post by Samuele Pedroni to the Python development mailing list
Samuele Pedroni to the Python-dev mailing list.
There was a long discussion regarding this...
Guido after Discussion
Conclusion
Python 2.2
The method resolution order is not monotonic
What is Monotonic?
The mro of a subclass is an extension without re-ordering of the mros of the superclasses.
A
B
C
D
X
(C A B)
(D B A)
MRO of C
MRO of D
Monotonic?
Subclass
A B or B A?
NO!
Can't decide, right?
1 2 2 1
MRO in Python3
- Inherits from 'object' implicitly
- uses new mro
Old MRO algorithm
Deep first, from Left to Right
DLR
Example:
class A:
def whoami(self):
print("I am A")
class B(A):
def whoami(self):
print("I am B")
class C(A):
def whoami(self):
print("I am C")
class D(B, C):
def whoami(self):
print("I am D")
d = D()
d.whoami()
Rule: DLR
D
B
A
C
A
D B A C
Depth first, from left to right
(Remove duplicates from end)
Summary
So in our example, algorithm search path is : D, B, A, C.
- Looking in D
- If not found, looking in B
- If not found, looking in B's first parent A
- If not found, going back in B others parents (none)
- If not found, looking in D's others parents : C
The C3 Algorithm
(Linearization of a Class)
Lets learn some notations first!
C1 C2 C3 C4 C5 C6 ........ CN
Head
Tail
- List of classes, head, tail
List of classes
- Sum of the list
Lets learn some notations first!
C + (C1 C2 ... CN) = C C1 C2 ... CN
(Notation for adding two lists)
The C3 Method Resolution Order
The list of the ancestors of a class C, including the class itself, ordered from the nearest ancestor to the furthest, is called the class precedence list or the linearization of C.
(Linearization of a Class C)
or
The MRO of C
The C3 Method Resolution Order
How to find Linearization of a Class C?
or MRO of class C
The linearization of C is the sum of C plus the merge of the linearizations of the parents and the list of the parents.
L[C(B1 ... BN)] = C + merge(L[B1] ... L[BN], B1 ... BN)
The C3 Method Resolution Order
Finding Merge
-
take the head of the first list.
-
if this head is not in the tail of any of the other lists, then add it to the linearization of C and remove it from the lists in the merge,
-
otherwise look at the head of the next list and take it, if it is a good head.
-
Then repeat the operation until all the class are removed or it is impossible to find good heads.
Example
O = object
class F(O): pass
class E(O): pass
class D(O): pass
class C(D,F): pass
class B(D,E): pass
class A(B,C): pass
O
D
E
F
B
C
A
Example
O
D
E
F
B
C
A
- L[O] = O
- L[D] = D O
- L[E] = E O
- L[F] = F O
Example 1
O
D
E
F
B
C
A
L[B] = B + merge(DO, EO, DE)
L[B]
= B +
merge(
L(D), L(E),
DE )
L[B] = B + D + merge(O, EO, E)
L[B] = B + D + E + merge(O, O)
L[B] = B + D + E + O
L[B] = B D E O
L[O] = O | L[D] = D O | L[E] = E O | L[F] = F O
There is no tail
here
Example 2
O
D
E
F
B
C
A
L[C] = C + merge(L[D], L[F], DF)
= C + D + merge(O, FO, F)
= C + D + F + merge(O,O)
= C D F O
= C + merge(DO, FO, DF)
L[O] = O | L[D] = D O | L[E] = E O | L[F] = F O
L[B] = B D E O
Example 3
O
D
E
F
B
C
A
L[A] = A + merge(BDEO, CDFO,BC)
= A + B + merge(DEO, CDFO,C)
= A + B + C + merge(DEO, DFO)
= A + B + C + D + merge(EO, FO)
= A + B + C + D + E + merge(O, FO)
= A + B + C + D + E + F + merge(O, O)
= A B C D E F O
L[O] = O | L[D] = D O | L[E] = E O | L[F] = F O
L[B] = B D E O | L[C] = C D F O
Questions?
Thank You!
@iaktech me@iamit.in
This work is licensed under a Creative Commons
Python MRO
By Amit Kumar
Python MRO
A Talk on Python Method Resolution Order.
- 6,903