python多重继承:避免以菱形形式调用构造函数两次

python多重继承:避免以菱形形式调用构造函数两次,python,initialization,multiple-inheritance,super,diamond-problem,Python,Initialization,Multiple Inheritance,Super,Diamond Problem,考虑以下代码: 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)._

考虑以下代码:

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
据我了解,算法如下:

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__
实际上有三个问题:
1.为什么
super()
2.在这种情况下,如何避免调用
C.\uuuuu init\uuuu
A.\uuuuu init\uuuuu
两次?
2.1初始化当前类继承自的所有类的正确方法是什么?

Q:为什么
super()。\uuuu init\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu()
B中调用

当你打电话的时候

super(X, self).__init__
Python查找self.\uuu类\uuuu.mro()
。然后,它从MRO中X之后的下一个类调用
\uuuuu init\uuuu

当self是
D
的实例时,
self.\uuu class\uuuu.mro()
[D,B,C,A]
。所以
super(B,self).\uuu init\uuu()
调用
C.\uu init\uuuu(self)


Q:初始化当前类继承自的所有类的正确方法是什么

D.\uuuuu init\uuuuu
中也使用super:

class D(B, C):
    def __init__(self):
        print("D.__init__")
        super(D, self).__init__()
        print("D.__init__ finished")
问:当self是D的一个实例时,为什么要调用
super()。\uuuuu init\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu

当你打电话的时候

super(X, self).__init__
Python查找self.\uuu类\uuuu.mro()
。然后,它从MRO中X之后的下一个类调用
\uuuuu init\uuuu

当self是
D
的实例时,
self.\uuu class\uuuu.mro()
[D,B,C,A]
。所以
super(B,self).\uuu init\uuu()
调用
C.\uu init\uuuu(self)


Q:初始化当前类继承自的所有类的正确方法是什么

D.\uuuuu init\uuuuu
中也使用super:

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

我贴了一个简化的箱子。实际的B类和C类有不同的签名。这是使用super的一种方法。签名必须全部匹配,因为您无法控制超级用户接下来调用哪个类的方法。为了平衡文章中的陷阱,也请阅读。我发布了一个简化的案例。实际的B类和C类有不同的签名。这是使用super的一种方法。签名必须全部匹配,因为您无法控制超级用户接下来调用哪个类的方法。为了平衡文章中的陷阱,也请阅读。