Learn with Yasir
Share Your Feedback

🧠 What is MRO?


🧠 What is MRO?

MRO stands for Method Resolution Order. It defines the order in which Python looks for methods and attributes in a hierarchy of classes when you use super().


🪜 Why is MRO Needed?

Consider a “diamond inheritance” like this:

     A
    / \
   B   C
    \ /
     D
  • All classes eventually inherit from A.
  • Without MRO, Python could accidentally call A multiple times — causing bugs.
  • MRO ensures that each class’s method (like __init__) is called once, and in a predictable order.

🔄 How MRO Works

Python uses the C3 Linearization Algorithm to compute MRO.

class A:
    def __init__(self):
        print("A initialized")

class B(A):
    def __init__(self):
        super().__init__()
        print("B initialized")

class C(A):
    def __init__(self):
        super().__init__()
        print("C initialized")

class D(B, C):
    def __init__(self):
        super().__init__()  # Initializes B -> C -> A
        print("D initialized")

d = D()  # Output order might surprise beginners

📦 Class Definitions

class A:
    def __init__(self):
        print("A initialized")
  • Base class A. It prints a message when initialized.
class B(A):
    def __init__(self):
        super().__init__()
        print("B initialized")
  • Class B inherits from A.
  • It calls super().__init__(), which refers to A.__init__.
class C(A):
    def __init__(self):
        super().__init__()
        print("C initialized")
  • Similarly, C inherits from A.
class D(B, C):
    def __init__(self):
        super().__init__()  # MRO applies here
        print("D initialized")
  • D inherits from both B and C. This is where MRO kicks in.

🤯 What Happens When You Call d = D()?

When we create an instance of D, the following happens:

  1. Python looks at the MRO (Method Resolution Order) of class D.
  2. D inherits from B and C, and both inherit from A. So Python uses C3 linearization to resolve this.

To see the MRO:

print(D.mro())

Output:

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

This means:

  1. Start at D
  2. Then look in B
  3. Then C
  4. Then A
  5. Finally, object (the root class of all Python classes)

🛠️ How super() Uses MRO

When you call super().__init__() inside D, Python uses the MRO list:

  • It goes to the next class after D → that’s B
  • B’s super() calls the next one → C
  • C’s super() calls the next → A
  • A doesn’t use super(), so it ends there

No class is repeated, and the initialization flows down this path.


🔄 Final Output Order:

A initialized
C initialized
B initialized
D initialized

Explanation:

  • D.__init__B.__init__C.__init__A.__init__
  • Then the print statements in reverse order as the stack unwinds.

📌 Summary

  • MRO ensures consistency in how classes are searched.
  • super() follows the MRO chain.
  • You can always check MRO with: ClassName.mro() or help(ClassName)
  • MRO prevents the diamond problem by avoiding multiple calls to the same base class.