I've converted your code to Python3 (by changing print
to print()
) and added some more tracing statements:
class A(object):
def __init__(self):
print("A", type(self).__mro__)
super(A, self).__init__()
print("/A")
class B(object):
def __init__(self):
print("B", type(self).__mro__)
super(B, self).__init__()
print("/B")
class C(A,B):
def __init__(self):
print("C")
A.__init__(self)
print("ca/b")
B.__init__(self)
print("/C")
C()
Here's the output:
C
A (<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>)
B (<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>)
/B
/A
ca/b
B (<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>)
/B
/C
Looking at the output, you can see the call to the C.__init__
method is happening, and printing 'C'. It then calls A.__init__
directly (which is a mistake- use super
!).
The A.__init__
call prints its message, including the __mro__
attribute. You can see the sequence: C -> A -> B -> Object. This is important, because it means that calls to super()
from within A.__init__
are going to refer to class B
. Also, calls to super
from inside C.__init__
would have invoked A.__init__
automatically, if you let them.
The next method, B.__init__
, is invoked by the super
reference inside A.__init__
, as mentioned. It calls Object.__init__
, presumably, which prints nothing. ;-)
Both B.__init__
and A.__init__
return, we see the midpoint message ca/b
, and then your direct call to B.__init__
is made. It prints a message, but again a reference to super
form B.__init__
does nothing, because B
is at the tail end of the MRO.
The super()
mechanism can deal with all this MRO stuff for you. You shouldn't have to invoke A.__init__(self)
. Instead, you can just let super
handle it, inside C.__init__
, but doing this:
class C(A,B):
def __init__(self):
print("C")
super(C, self).__init__()