How Python Method Resolution Order (MRO) Works
Ariful Islam (Palash)
Senior Software Engineer at BRAC IT | Backend | Python | Django | Golang
1. Definition and Purpose:
- MRO defines the order in which Python looks for methods in the class hierarchy.
- It is important to determine which method is called when multiple base classes define a method with the same name.
2. C3 Linearization:
- Python uses an algorithm called C3 Linearization to compute the MRO. This algorithm ensures a consistent and predictable method resolution order.
3. Algorithm Details:
- Base Class Order: The MRO is computed by considering the order of base classes and ensuring that each base class appears before its parents.
- Parents' MRO: The MRO of each parent class is also considered, ensuring that the MRO of parents is respected in the order.
- Resolution: The algorithm merges the MROs of base classes, following a left-to-right, depth-first search approach.
4. Steps in MRO Computation:
- Initialize: Start with the MRO of the class itself and the MROs of its base classes.
- Merge MROs: Merge the MROs of the base classes into the MRO of the class. This involves:
- Picking the first class that hasn’t been included yet and whose MRO is compatible with the current MRO.
- Removing that class from the list of potential candidates and including it in the MRO.
- Repeat: Continue merging until all classes are included in the MRO.
5. Example:
```python
class A:
def method(self):
print("A")
class B(A):
领英推荐
def method(self):
print("B")
class C(A):
def method(self):
print("C")
class D(B, C):
pass
d = D()
d.method() # Output: B
In this example, the MRO for class D is computed as follows:
- D inherits from B and C.
- B is checked before C because B appears first in the inheritance list.
- The MRO for D is [D, B, C, A].
6. Viewing MRO: :
- You can view the MRO of a class using the mro attribute or the mro() method
print(D.__mro__) # (<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)
print(D.mro()) # [<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]