Your mistake is in your comment:
super(C, self).__init__() <-- call to object.__init__()
This is not a call to object.__init__
. The reason that you pass both the class C and the instance self
to super
is so that it knows what to call next, not just based on the superclasses of the class, but based on the MRO of the instance. Essentially, super(C, self).__init__
means "call the __init__
of the class after C in self's MRO".
This is the whole point of super
--- it allows cooperative inheritance where a class can just call super
to mean "pass control the next class in the MRO", without needing to know at class definition time which class that is.
So when you call super(C, self).__init__
, that calls A.__init__
, because A is the next class after C in the MRO. Then when A calls super(A, self).__init__
, that calls B.__init__
, because B is the class after A in the MRO.
(Note that your messages are printed in reverse order --- B, A, C --- because you print each message after calling the superclass method. So the first message doesn't get printed until executing gets all the way up to B.__init__
, and then the other messages are printed on the way back down the inheritance tree.)