5.13. OOP Inheritance MRO

  • MRO - Method Resolution Order

  • Inheritance Diamond

5.13.1. Problem

>>> class Person:
...     def __init__(self):
...         print('Person')
>>>
>>>
>>> class Astronaut(Person):
...     def __init__(self):
...         print('Astronaut')
>>>
>>>
>>> class Cosmonaut(Person):
...     def __init__(self):
...         print('Cosmonaut')
>>>
>>>
>>> class Crew(Astronaut, Cosmonaut):
...     def __init__(self):
...         print('Crew')
>>>
>>>
>>> crew = Crew()
Crew

5.13.2. Small Diamond

../../_images/oop-mro-diamond-small-empty.png
>>> class Person:
...     def __init__(self):
...         print('Person')
>>>
>>>
>>> class Astronaut(Person):
...     def __init__(self):
...         print('Astronaut')
>>>
>>>
>>> class Cosmonaut(Person):
...     def __init__(self):
...         print('Cosmonaut')
>>>
>>>
>>> class Crew(Astronaut, Cosmonaut):
...     pass
>>>
>>>
>>> crew = Crew()
Astronaut
>>> class Person:
...     def __init__(self):
...         print('Person')
>>>
>>>
>>> class Astronaut(Person):
...     def __init__(self):
...         print('Astronaut')
>>>
>>>
>>> class Cosmonaut(Person):
...     def __init__(self):
...         print('Cosmonaut')
>>>
>>>
>>> class Crew(Astronaut, Cosmonaut):
...     def __init__(self):
...         super().__init__()
>>>
>>>
>>> crew = Crew()
Astronaut
../../_images/oop-mro-diamond-small-path.png
>>> Crew.mro()  
[<class '__main__.Crew'>,
 <class '__main__.Astronaut'>,
 <class '__main__.Cosmonaut'>,
 <class '__main__.Person'>,
 <class 'object'>]
>>> Crew.__mro__  
(<class '__main__.Crew'>,
 <class '__main__.Astronaut'>,
 <class '__main__.Cosmonaut'>,
 <class '__main__.Person'>,
 <class 'object'>)

5.13.3. Large Diamond

../../_images/oop-mro-diamond-large-empty.png
>>> class Person:
...     def __init__(self):
...         print('Person')
>>>
>>>
>>> class Astronaut(Person):
...     def __init__(self):
...         print('Astronaut')
>>>
>>> class VeteranAstronaut(Astronaut):
...     def __init__(self):
...         print('VeteranAstronaut')
>>>
>>>
>>> class Cosmonaut(Person):
...     def __init__(self):
...         print('Cosmonaut')
>>>
>>> class VeteranCosmonaut(Cosmonaut):
...     def __init__(self):
...         print('VeteranCosmonaut')
>>>
>>>
>>> class Crew(VeteranAstronaut, VeteranCosmonaut):
...     def __init__(self):
...         super().__init__()
>>>
>>>
>>> crew = Crew()
VeteranAstronaut
>>> class Person:
...     def __init__(self):
...         print('Person')
>>>
>>>
>>> class Astronaut(Person):
...     def __init__(self):
...         print('Astronaut')
>>>
>>> class VeteranAstronaut(Astronaut):
...     def __init__(self):
...         super().__init__()
...         print('VeteranAstronaut')
>>>
>>>
>>> class Cosmonaut(Person):
...     def __init__(self):
...         print('Cosmonaut')
>>>
>>> class VeteranCosmonaut(Cosmonaut):
...     def __init__(self):
...         super().__init__()
...         print('VeteranCosmonaut')
>>>
>>>
>>> class Crew(VeteranAstronaut, VeteranCosmonaut):
...     pass
>>>
>>>
>>> crew = Crew()
Astronaut
VeteranAstronaut

5.13.4. Problematic super()

>>> class Person:
...     def __init__(self):
...         print('Person')
>>>
>>>
>>> class Astronaut(Person):
...     def __init__(self):
...         print('Astronaut')
...         super().__init__()
>>>
>>> class VeteranAstronaut(Astronaut):
...     def __init__(self):
...         print('VeteranAstronaut')
...         super().__init__()
>>>
>>>
>>> class Cosmonaut(Person):
...     def __init__(self):
...         print('Cosmonaut')
...         super().__init__()
>>>
>>> class VeteranCosmonaut(Cosmonaut):
...     def __init__(self):
...         print('VeteranCosmonaut')
...         super().__init__()
>>>
>>>
>>> class Crew(VeteranAstronaut, VeteranCosmonaut):
...     pass
>>>
>>>
>>> crew = Crew()
VeteranAstronaut
Astronaut
VeteranCosmonaut
Cosmonaut
Person

5.13.5. Why?!

  • Raymond Hettinger - Super considered super! - PyCon 2015 1

../../_images/oop-mro-diamond-large-path.png
>>> Crew.mro()  
[<class '__main__.Crew'>,
 <class '__main__.VeteranAstronaut'>,
 <class '__main__.Astronaut'>,
 <class '__main__.VeteranCosmonaut'>,
 <class '__main__.Cosmonaut'>,
 <class '__main__.Person'>,
 <class 'object'>]

5.13.6. Compare

../../_images/oop-mro-diamond-both-path.png

5.13.7. References

1

https://www.youtube.com/watch?v=EiOglTERPEo