2017-02-14 56 views
0

最近我读了一本书,它提到了多重继承的MRO,并给出示例代码:蟒蛇多重继承输出问题

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

class B(object): 
    def __init__(self): 
     print "B" 
     super(B, self).__init__() 

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

C() 

输出:

C 
A 
B 
B 

我想知道为什么会这样发生?

回答

2

发生这种情况是因为您正在通过super混合直接构造函数调用和调用。你的类层次结构应该做任何一个或另一个。

更确切地说,类别C的MRO是C, A, B。因此,当您在A的构造函数中调用super(A, self).__init__()时,该函数调用B的构造函数,因为B成功在C的MRO中成功执行A。换句话说,它是在第一个B打印的A的构造函数内。

另外,写出super(A, self)在Python 3中是多余的。super()就够了;来自上下文的参数是deduced

延伸阅读:

0

我已经转换你的代码Python3(通过改变printprint()),并增加了一些更多的跟踪语句:

class A(object): 
    def __init__(self): 
     print("A", type(self).__mro__) 
     super(A, self).__init__() 
     print("/A") 

class B(object): 
    def __init__(self): 
     print("B", type(self).__mro__) 
     super(B, self).__init__() 
     print("/B") 

class C(A,B): 
    def __init__(self): 
     print("C") 
     A.__init__(self) 
     print("ca/b") 
     B.__init__(self) 
     print("/C") 

C() 

下面是输出:

C 
A (<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>) 
B (<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>) 
/B 
/A 
ca/b 
B (<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>) 
/B 
/C 

望着输出,你可以看到调用C.__init__方法正在发生的事情,并打印“C”。然后直接调用A.__init__(这是一个错误 - 使用super!)。

A.__init__调用打印其消息,包括__mro__属性。您可以看到序列:C - > A - > B - > Object。这很重要,因为这意味着从A.__init__内调用super()将参考类B。另外,如果您允许,自C.__init__内部调用super将自动调用A.__init__

如上所述,下一个方法B.__init__A.__init__内的super引用调用。它叫Object.__init__,据推测,这不会打印任何东西。 ;-)

两个B.__init__A.__init__回报,我们看到的中点消息ca/b,然后你到B.__init__直接调用。它会打印一条消息,但再次参考super表单B.__init__什么也不做,因为B位于MRO的尾部。

super()机制可以为您处理所有这些MRO的东西。您不应该调用A.__init__(self)。相反,你可以让super处理它,里面C.__init__,但是这样做:

class C(A,B): 
    def __init__(self): 
     print("C") 
     super(C, self).__init__() 
+0

这是如此之大!谢谢 – TreeCatCat