Question

In the documentation on the Python webpage the method resolution order for classic classes in python is described as a depth-first left-to-right search. I tried to test this with this piece of code:

class A(object):
def __init__(self):
    print "Initialized A"

class B(A):
    def test():
        print "Initialized B"

class C(A):
    def __init__(self):
        print "Initialized C"

class D(B, C):
    def __init__(self):
        super(D, self).__init__()
        print "Initialized D"

When I create an instance of object D:

D()

I get the result:

Initialized C
Initialized D

While I expected the prints "Initialized A", "Initialized D" since the MRO is depth-first, the initialization is first searched in B, when not found (which is the case) it should go deeper in the hierarchy and look for the function in the base class of B (i.e. A). Can someone give me an explanation why I get the init-function of C instead of that one of A?

Was it helpful?

Solution 2

Your class inherits from object and is thus not a classic class. It is a new-style class. (Any class that inherits from a new-style class is also a new-style class.)

Note that super can't be used with classic classes anyway. The "depth first left to right" rule you cite is just the attribute lookup rule for the order base classes are searched when you try to access an attribute that is not directly defined on the instance. Classic classes don't provide an MRO as such --- there isn't any way to access "the superclass value" of an attribute without explicitly referencing a particular superclass.

OTHER TIPS

The MRO of D is:

print(D.mro())
[<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <type 'object'>]

So

super(D, self).__init__()

looks for an __init__ method in the first class in self.__class__.mro() after D. Since B does not have an __init__, it then looks for an __init__ method in C. It finds C.__init__, and therefore

super(D, self).__init__()

calls C.__init__(self).

Notice that super is not trying to access getattr(B, __init__). Rather, it is looking for '__init__' in B.__dict__.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top