Trusted answers to developer questions

What is MRO in Python?

Get the Learn to Code Starter Pack

Break into tech with the logic & computer science skills you’d learn in a bootcamp or university — at a fraction of the cost. Educative's hand-on curriculum is perfect for new learners hoping to launch a career.

Method Resolution Order

MRO is a concept used in inheritance. It is the order in which a method is searched for in a classes hierarchy and is especially useful in Python because Python supports multiple inheritancea method being called from a child object may exist in multiple super classes.

In Python, the MRO is from bottom to top and left to right. This means that, first, the method is searched in the class of the object. If it’s not found, it is searched in the immediate super class. In the case of multiple super classes, it is searched left to right, in the order by which was declared by the developer. For example:

def class C(B, A)

Note: We are using Python 3.10.4 in this Answer.

In this case, the MRO would be C -> B -> A.
Since B was mentioned first in the class declaration, it will be searched for first while resolving a method.

Let’s look at a few cases, starting from simple to complex.

Example 1

class A:
def method(self):
print("A.method() called")
class B(A):
def method(self):
print("B.method() called")
b = B()
b.method()

This is a simple case with single inheritance. In this case, when b.method() is called, it first searches for the method in class B. In this case, class B had defined the method; hence, it is the one that was executed. In the case where it is not present in B, then the method from its immediate super class (A) would be called. So, the MRO for this case is: B -> A

Example 2

class A:
def method(self):
print("A.method() called")
class B:
pass
class C(B, A):
pass
c = C()
c.method()

The MRO for this case is:
C -> B -> A
The method only existed in A, where it was searched for last.

Example 3

class A:
def method(self):
print("A.method() called")
class B:
def method(self):
print("B.method() called")
class C(A, B):
pass
class D(C, B):
pass
d = D()
d.method()

The MRO for this can be a bit tricky. The immediate superclass for D is C, so if the method is not found in D, it is searched for in C. However, if it is not found in C, then you have to decide if you should check A (declared first in the list of C’s super classes) or check B (declared in D’s list of super classes after C). In Python 3 onwards, this is resolved as first checking A. So, the MRO becomes:

D -> C -> A -> B

Learn about C3 Linearization to see why.

When can an exception occur?

If, as in example 3 (shown above):

  • The order of inheritance of D is (B, C, object) object ensures that it is a new style class
  • The order of inheritance of C is (B, A)

It would give an error:
TypeError: Cannot create a consistent method resolution order (MRO) for bases B, C.

Explanation:
The MRO that we can deduce from the rules we have seen is: D -> B -> C -> B -> A
However, B should not come before C as it is a super class of C. So, it becomes:
D -> C -> B -> A
But, while declaring the class D, B was declared first in the list of super classes; so, if a method exists in both B and C, which version should called?

RELATED TAGS

python

CONTRIBUTOR

Fatima Hasan
Copyright ©2024 Educative, Inc. All rights reserved
Did you find this helpful?