Search code examples
pythonoopinheritancemultiple-inheritancemethod-resolution-order

Python Method Resolution Order


Could someone explain the output of given code and how python MRO works in this case?

class A(object):
    def go(self):
        print("go A go!")


class B(A):
    def go(self):
        super(B, self).go()
        print("go B go!")


class C(A):
    def go(self):
        super(C, self).go()
        print("go C go!")


class D(C, B):
    def go(self):
        super(D, self).go()
        print("go D go!")


d = D()
d.go()

Output:

go A go!
go B go!
go C go!
go D go!

Following left-to-right and depth I would say it should be:

go A go!
go C go!
go D go!

but seems it dosn't work as I thought.


Solution

  • The MRO for a class is based on the MRO of it parents:

    >>> A.__mro__
    (<class '__main__.A'>, <class 'object'>)
    >>> B.__mro__
    (<class '__main__.B'>, <class '__main__.A'>, <class 'object'>)
    >>> C.__mro__
    (<class '__main__.C'>, <class '__main__.A'>, <class 'object'>)
    >>> D.__mro__
    (<class '__main__.D'>, <class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>)
    

    The three rules are:

    1. Children go before parents:
    • A < object
    • B < A
    • C < A
    • D < C
    • D < B
    1. Parents go in the order of bases:
    • C < B
    1. Parent mros are merged, preserving their order.
    • merge B < A < object with C < A < object

    In the early days of Python 2, the search rule used to be depth-first-left-ot-right, but that changed based on research into the C3 linearization algorithm.

    See the Super Considered Super blog post for ways to take advantage of this algorithm in real code.