Jacob's answer shows how to understand the problem, while batbrat shows the details, and hrr goes straight to the point.
One thing that they do not cover (at least not an explanation) from your question is this:
However, if you comment out the super call in function B init, function A or C init is not called.
To understand this, change Jacob's code to print the stack to A init, as shown below:
import traceback class A(object): def __init__(self): print "A init" print self.__class__.__mro__ traceback.print_stack() class B(A): def __init__(self): print "B init" print self.__class__.__mro__ super(B, self).__init__() class C(A): def __init__(self): print "C init" print self.__class__.__mro__ super(C, self).__init__() class D(B, C): def __init__(self): print "D init" print self.__class__.__mro__ super(D, self).__init__() x = D()
It's a little surprising to see that the line B super(B, self).__init__() actually calls C.__init__() , since C not a base class of B
D init (<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <type 'object'>) B init (<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <type 'object'>) C init (<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <type 'object'>) A init (<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <type 'object'>) File "/tmp/jacobs.py", line 31, in <module> x = D() File "/tmp/jacobs.py", line 29, in __init__ super(D, self).__init__() File "/tmp/jacobs.py", line 17, in __init__ super(B, self).__init__() File "/tmp/jacobs.py", line 23, in __init__ super(C, self).__init__() File "/tmp/jacobs.py", line 11, in __init__ traceback.print_stack()
This is because super (B, self) does not "invoke the B-base version of B __init__ ". Instead, it "calls __init__ in the first class to the right of B , which is present on self __mro__ and has such an attribute.
So, if you comment out the super call in the B init function, the method stack will stop at B.__init__ and never reach C or A
Summarizing:
- No matter which class refers to it,
self always refers to an instance, and its __mro__ and __class__ remain constant - super () finds a method that looks at classes that are to the right of the current one in
__mro__ . Since the __mro__ constant remains constant, what happens is that it is searched as a list, and not as a tree or graph.
At this last point, note that the full name of the MRO algorithm is a linearization of the superclass C3. That is, it aligns this structure in the list. When various super() calls occur, they effectively repeat this list.