Your mistake in your comment:
super(C, self).__init__() <-- call to object.__init__()
This is not a call to object.__init__ . The reason you pass both the C class and the self instance to super is because it knows what to call next, not only based on the superclasses of the class, but based on the MRO instance. Essentially, super(C, self).__init__ means "call the __init__ class after C in self MRO."
This is the whole point of super --- it allows co-inheritance, when a class can simply call super mean "transfer control to the next class in the MRO", without having to know the time the class was defined, which class.
Therefore, when you call super(C, self).__init__ , which calls A.__init__ , because A is the next class after C in the MRO. Then, when A calls super(A, self).__init__ , which calls B.__init__ , because B is the class after A in the MRO.
(Note that your messages are printed in the reverse order --- B, A, C --- because you print each message after calling the superclass method. Therefore, the first message does not print until execution is fully started until B.__init__ , and then other messages are printed on the return path through the inheritance tree.)
source share