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

时间:2012-09-17 10:41:30

标签: 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).__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().__init__()B.__init__的实例时,为什么C.__init__拨打self(2)来拨打D? 2.在这种情况下,如何避免两次致电C.__init__A.__init__? 2.1初始化当前类继承的所有类的正确方法是什么?

1 个答案:

答案 0 :(得分:5)

问:当自我是D的实例时,为什么super().__init__()B.__init__(2)中拨打电话C.__init__

致电时

super(X, self).__init__

Python查找the MRO self.__class__.mro()。然后它会在X之后从MRO中的 next 类调用__init__

当self是D的实例时,self.__class__.mro()[D, B, C, A]。因此super(B, self).__init__()会调用C.__init__(self)


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

D.__init__中使用super:

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