Method Resolution order

  • MRO defines the order in which the base classes are searched when executing a method.
  • First, the method or attribute is searched within a class and then it follows the order we specified while inheriting

Simple MRO-1

class A1:
    def rk(self):
        print(" In class A1")
class B1(A1):
    def rk(self):
        print(" In class B1")
r = B1()
r.rk()
print(B1.mro())
# [<class '__main__.B'>, <class '__main__.A'>, <class 'object'>]

Simple MRO-2

class A:
    def rk(self):
        print(" In class A")
class B(A):
    def rk(self):
        print(" In class B")
class C(A):
    def rk(self):
        print("In class C")
class D(B, C):      # First B
    pass
r = D()
r.rk()
print(D.mro())

# [<class '__main__.D'>, <class '__main__.B'>,
# <class '__main__.C'>, <class '__main__.A'>,
# <class 'object'>]

Complex MRO-1

  • Old style classes use DLR or depth-first left to right algorithm
  • whereas new style classes use C3 Linearization algorithm
class X:
    pass
class Y:
    pass
class Z:
    pass
class ZZ:
    pass
class A(X, Y):
    pass
class B(Z, ZZ):
    pass
class M(B, A):
    pass
print(M.mro())

# M B Z ZZ A X Y
# [<class '__main__.M'>, <class '__main__.B'>,
# <class '__main__.Z'>, <class '__main__.ZZ'>,
# <class '__main__.A'>, <class '__main__.X'>,
# <class '__main__.Y'>, <class 'object'>]

Complex MRO-2

class X:
    pass
class Y:
    pass
class Z:
    pass
class ZZ:
    pass
class A(X, Y):
    pass
class B(Z, Y):
    pass
class M(B, A, ZZ):
    pass
print(M.mro())

# M B Z Y A X Y ZZ  --> last Y is considered
# [<class '__main__.M'>, <class '__main__.B'>,
# <class '__main__.Z'>, <class '__main__.A'>,
# <class '__main__.X'>, <class '__main__.Y'>,
# <class '__main__.ZZ'>, <class 'object'>]

Complex MRO-3

class X:
    pass
class Y:
    pass
class Z:
    pass
class A(X, Y):
    pass
class B(Y, Z):
    pass
class M(B, A, Z):
    pass
print(M.mro())

# M B Y Z A X Y Z --> M B A X Y Z -->  last class is considered
# [<class '__main__.M'>, <class '__main__.B'>,
# <class '__main__.A'>, <class '__main__.X'>,
# <class '__main__.Y'>, <class '__main__.Z'>,
# <class 'object'>]

TypeError: Cannot create a consistent method resolution

class A:
	pass
class B:
	pass
class X:
    pass
class C(A, B):
	pass
class D(B, A):  	# Fails
	pass			
class E(C,D):
	pass
print(E.mro())

# E C A B D B A -- ISSUE
# Fails, coz prev order was A, B -- in C 
# But new order become B, A  -- D