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