0

Consider the following code:

class A(object):
    def __init__(self):
        print("A.__init__")
        super(A, self).__init__()          # 1
        print("A.__init__ finished")

class B(A):
    def __init__(self):
        print("B.__init__")
        super(B, self).__init__()          # 2
        print("B.__init__ finished")

class C(A):
    def __init__(self):
        print("C.__init__")
        super(C, self).__init__()
        print("C.__init__ finished")

class D(B, C):
    def __init__(self):
        print("D.__init__")
        print("Initializing B")
        B.__init__(self)                   # 3
        print("B initialized")
        print("Initializing C")
        C.__init__(self)                   # 4
        print("C initialized")
        print("D.__init__ finished")

D()

# D.__init__
# Initializing B
# B.__init__
# C.__init__
# A.__init__
# A.__init__ finished
# C.__init__ finished
# B.__init__ finished
# B initialized
# Initializing C
# C.__init__
# A.__init__
# A.__init__ finished
# C.__init__ finished
# C initialized
# D.__init__ finished

As far as I understand, the algorithm is as follows:

D.__init__ at (3) -> B.__init__ -> 
-> super().__init__ -> (super of self.__class__).__init__ ->
-> C.__init__ (# why C?) -> super().__init__ -> 
-> A.__init__

D.__init__ at (4) -> C.__init__ ->
-> super().__init__ -> 
-> A.__init__

Actually there are three questions:
1. Why super().__init__() call in B.__init__ (at 2) calls C.__init__ when self is an instance of D?
2. How to avoid calling C.__init__ and A.__init__ twice in this case?
2.1 What is the right way to initialize all the classes the current class inherits from?

1 Answer 1

5

Q: Why super().__init__() call in B.__init__ (at 2) calls C.__init__ when self is an instance of D?

When you call

super(X, self).__init__

Python looks up the MRO self.__class__.mro(). It then calls __init__ from the next class in the MRO after X.

When self is an instance of D, self.__class__.mro() is [D, B, C, A]. So super(B, self).__init__() calls C.__init__(self).


Q: What is the right way to initialize all the classes the current class inherits from?

Use super in D.__init__ as well:

class D(B, C):
    def __init__(self):
        print("D.__init__")
        super(D, self).__init__()
        print("D.__init__ finished")
Sign up to request clarification or add additional context in comments.

2 Comments

I posted a simplified case. Actual classes B and C have different signature.
The is one of the pitfalls of using super. The signatures must all match, because you can not control which classes's method is called next by super. As a counterbalance to the pitfalls article, also read Hettinger's take on super().

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.