Amit Kumar
Software Engineer, creator of https://cirun.io
Amit Kumar | @aktech | me@iamit.in
v2.0
Method Resolution Order
defines the class search path used by Python to search for the right method to use in classes having multi-inheritance.
class A:
def whoami(self):
print("I am A")
class B(A):
def whoami(self):
print("I am B")
class C(A, B):
pass
object_c = C()
object_c.whoami()
?
Two algorithms to find Method Resolution Order
Old MRO
New MRO
Old Classes
New Classes
(C3 Algorithm)
class A :
pass
class B :
pass
class C(A, B) :
pass
class A(object) :
pass
class B(object) :
pass
doesn't inherits from Python root object class.
introduced in python 2.3
(Brief History)
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
The method resolution order is not 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
Subclass
A B or B A?
Can't decide, right?
1 2 2 1
Deep first, from Left to Right
DLR
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)
So in our example, algorithm search path is : D, B, A, C.
(Linearization of a Class)
C1 C2 C3 C4 C5 C6 ........ CN
Head
Tail
List of classes
C + (C1 C2 ... CN) = C C1 C2 ... CN
(Notation for adding two lists)
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
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)
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.
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
O
D
E
F
B
C
A
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
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
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
@iaktech me@iamit.in
This work is licensed under a Creative Commons
By Amit Kumar
A Talk on Python Method Resolution Order.