Method Resolution Order (MRO)
Arvind Padmanabhan
Indian Engineering
Design Forum
August 2013
http://iedf.in
Devopedia
February 2017
http://devopedia.org
The Linear Pattern
MRO
- HappyPerson
- FamilyPerson
- Husband
- Father
- Professional
- SelfEmployed
- CharteredAccountant
Code
- HappyPerson.mro()
- HappyPerson.__mro__
The Diamond Pattern
MRO
- Romantic19Novel
- RomanticNovel
- NineteenthCenturyNovel
- Novel
- Book
Code
- Romantic19Novel.mro()
- Romantic19Novel.__mro__
Summary
- Multiple inheritance is not confusing if the call hierarchy is clearly understood:
- Calls are depth first but where a common ancestor is involved, it is called as late as possible
- Strictly speaking, everything in Python is a diamond pattern since all classes are based on object class, which is called last
- Method mro() can be called on the class, not an object
Test Yourself
MRO
- M
- A
- X
- B
- Y
- Z
- object
Code (Linear)
class Husband:
def __init__(self):
super().__init__()
class Father:
def __init__(self):
super().__init__()
class FamilyPerson(Husband, Father):
def __init__(self):
super().__init__()
class SelfEmployed:
def __init__(self):
super().__init__()
class CharteredAccountant:
def __init__(self):
super().__init__()
class Professional(SelfEmployed, CharteredAccountant):
def __init__(self):
super().__init__()
class HappyPerson(FamilyPerson, Professional):
def __init__(self):
super().__init__()
if __name__ == '__main__':
hp = HappyPerson()
print(HappyPerson.mro()) # list
print(HappyPerson.__mro__) # tuple
try:
print(hp.mro()) # list
print(hp.__mro__) # tuple
except AttributeError:
print('Cannot call MRO on an object. Call it on the class.')
Code (Diamond)
class Book:
def __init__(self):
super().__init__()
class Novel(Book):
def __init__(self):
super().__init__()
class MurderNovel(Novel):
def __init__(self):
super().__init__()
class RomanticNovel(Novel):
def __init__(self):
super().__init__()
class NineteenthCenturyNovel(Novel):
def __init__(self):
super().__init__()
class Romantic19Novel(RomanticNovel, NineteenthCenturyNovel):
def __init__(self):
super().__init__()
if __name__ == '__main__':
mn = MurderNovel()
r19n = Romantic19Novel()
print(Romantic19Novel.mro()) # list
print(Romantic19Novel.__mro__) # tuple
try:
print(r19n.mro()) # list
print(r19n.__mro__) # tuple
except AttributeError:
print('Cannot call MRO on an object. Call it on the class.')
# Another example
class X: pass
class Y: pass
class Z: pass
class A(X, Y): pass
class B(Y, Z): pass
class M(A, B, Z): pass
print(M.mro())
MRO
By Arvind Padmanabhan
MRO
About Python's Method Resolution Order.
- 2,710