Skip to content

What is MRO (Method Resolution Order)?

Method Resolution Order (MRO) is a mechanism in Python that determines the order in which base classes are looked up when searching for a method. This is particularly important in object-oriented programming, especially when dealing with multiple inheritance.


Why is MRO Important?

When a method is called on an object, Python needs to know which class's method to execute if the method exists in multiple classes due to inheritance. MRO helps Python decide this order systematically.

Key Concepts

1. Single Inheritance:

  • In single inheritance, if you have a class that inherits from another, the MRO is straightforward:
class Parent:
    def greet(self):
        return "Hello from Parent!"

class Child(Parent):
    pass

child = Child()
print(child.greet())  # Calls greet from Parent

2. Multiple Inheritance:

  • With multiple inheritance, MRO becomes more complex. If a class inherits from multiple classes, MRO determines which parent class's method to use.

  • For example:

class A:
    def method(self):
        return "Method from A"

class B(A):
    pass

class C(A):
    def method(self):
        return "Method from C"

class D(B, C):
    pass

obj = D()
print(obj.method())  # Determines which method to use

3. Using the mro() Method:

  • You can view the MRO of a class using the mro() method or the __mro__ attribute:
print(D.mro())       # Outputs: [<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]
print(D.__mro__)     # Same as above

How MRO Works

Python uses the C3 linearization algorithm (also known as C3 superclass linearization) to determine the MRO. The key rules of this algorithm are:

  1. The method resolution order must respect the order of the base classes.
  2. A class can only come after its parents.
  3. If a class appears as a base class in multiple places, it must be listed only once.

Example Walkthrough

Let's analyze the earlier D class example:

class A:
    def method(self):
        return "Method from A"

class B(A):
    pass

class C(A):
    def method(self):
        return "Method from C"

class D(B, C):
    pass
  • MRO for D:
  • Start with D.
  • Check B (first base class).
  • Next, check C (second base class).
  • Finally, check A (the common ancestor).

The MRO will be [D, B, C, A, object].

Conclusion

MRO is crucial in Python for resolving which method to call in a hierarchy of classes, particularly with multiple inheritance. Understanding it helps you design your classes more effectively and avoid common pitfalls associated with method resolution.


Additional

now explain mro to 5 years old

Sure! Let's use a simple story to explain MRO.

Imagine a Family Tree

Imagine you have a family with different members:

  1. Grandma (A)
  2. Mom (B), who learned from Grandma.
  3. Aunt (C), who also learned from Grandma.
  4. You (D), who learned from both Mom and Aunt.

Now, when you want to bake cookies, you might ask one of them for the recipe. But who do you ask first?

The Order of Asking

  1. First, you ask your Mom (B) because she’s closest to you.
  2. If she doesn’t know, you then ask your Aunt (C).
  3. Finally, if neither of them knows, you ask Grandma (A).

The Rule of Asking

This order of asking is like MRO (Method Resolution Order)! It tells you who to ask first when you want to find something out.

So, in our family:

  • You always check with Mom first,
  • Then Aunt,
  • And then Grandma.

Summary

MRO helps decide the order to ask for help in a family, just like how Python decides which method to use in a group of classes.