peter.slizik
peter.slizik

Reputation: 2076

Python - Peculiarities in method resolution order

Let's have the following Python2 code:

#!/usr/bin/python

class A1(object):
    def __init__(self):
        super(A1, self).__init__()
        print "A1.__init__"

class A2(A1):
    def __init__(self):
        super(A2, self).__init__()
        print "A2.__init__"

class B1(object):
    def __init__(self):
        super(B1, self).__init__()
        print "B1.__init__"

class B2(B1):
    def __init__(self):
        super(B2, self).__init__()
        print "B2.__init__"

class C(A2, B2):
    def __init__(self):
        super(C, self).__init__()
        print "C.__init__"

C()
print C.mro()

That is, C inherits from two predecessor class branches, which have no mutual ancestor (except for the default object, not sure how important this is). The code outputs:

B1.__init__
B2.__init__
A1.__init__
A2.__init__
C.__init__
[<class '__main__.C'>, <class '__main__.A2'>, <class '__main__.A1'>, <class '__main__.B2'>, <class '__main__.B1'>, <type 'object'>]

Exactly as expected.

Now say that I'm careless and forget to call super().__init__() in A1 and B1 (I don't care about initializing object that much...). The output then changes to:

A1.__init__
A2.__init__
C.__init__
[<class '__main__.C'>, <class '__main__.A2'>, <class '__main__.A1'>, <class '__main__.B2'>, <class '__main__.B1'>, <type 'object'>]

Now only the A1-A2 branch was initialized - while C.mro() had not changed at all!

What is the reason of this behavior?

Upvotes: 0

Views: 38

Answers (2)

peter.slizik
peter.slizik

Reputation: 2076

Okay, to answer my own question: the thing that confused me (failing to call super() in a class that inherits directly form object) is described here in detail:

https://fuhm.net/super-harmful/

Upvotes: 0

Daniel Roseman
Daniel Roseman

Reputation: 599620

The printout of the MRO shows you exactly why this is. Python calls the parent methods in that specific order, hence the name. It calls A2's method, which has a super call so then calls A1's method; but A1 does not in turn call super so the chain stops there.

Upvotes: 2

Related Questions