
The __mro__ Attribute in Python
The `__mro__` (Method Resolution Order) attribute is a tuple that shows the order in which Python searches for methods and attributes in the classes involved in the inheritance hierarchy.
class.__mro__
Simply put, if you have a class that inherits from other classes, `__mro__` tells you the order in which Python will check these classes to find a method or attribute.
Why is it important? Understanding the method resolution order is essential when working with multiple inheritance in Python. It helps you predict which method will be called, preventing unexpected behaviors and difficult-to-diagnose bugs.
Here's a simple example to see how it works in practice:
Imagine you have a straightforward class hierarchy:
class A:
def method(self):
return "Method in A"
class B(A):
def method(self):
return "Method in B"
class C(A):
def method(self):
return "Method in C"
class D(B, C):
pass
In this example, `D` inherits from `B` and `C`, which both inherit from `A`.
Let's see what `__mro__` tells us:
print(D.__mro__)
The output will be:
(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)
This means that if you call the `method` method on an instance of `D`, Python will look for the method in this order:
- Class `D`
- Class `B`
- Class `C`
- Class `A`
- Class `object` (the base class of all classes in Python)
For example, try creating an instance of class D:
d = D()
Then, call the method:
print(d.method())
The output will be:
Method in B
Python found the `method` in `B` before `C`, so it called the one in `B`.
In the method resolution order, Python looks for the method to execute following the order in the MRO attribute. If it doesn't find it in one class, it checks the next one in the hierarchy.
What happens if you change the order of the base classes in `D`?
Let's try changing the inheritance order:
class A:
def method(self):
return "Method in A"
class B(A):
def method(self):
return "Method in B"
class C(A):
def method(self):
return "Method in C"
class D(C,B ):
pass
Now class D inherits from C first and then from B.
print(D.__mro__)
(<class '__main__.D'>, <class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>)
Create an instance of class D again:
d = D()
Then, call the method:
print(d.method())
Method in C
This time, Python follows the resolution order and finds `method` in `C` before `B`.
Python uses an algorithm called C3 Linearization to determine the method resolution order. This algorithm ensures that the method resolution order is deterministic and respects Python's inheritance rules.
I hope this guide has helped you better understand the `__mro__` attribute and how to use it in your Python projects.