Mat*_*son 12

我不确定python教程的作者所指的是什么限制,但我猜它部分与在python中实现方法/属性查找的方式有关("方法解析顺序"或MRO).Python使用C3超类线性化机制; 这是为了处理所谓的" 钻石问题 ".

一旦你在类层次结构中引入了多个继承,任何给定的类都没有它继承的单个潜在类,它只有"MRO中的下一个类",即使对于期望它们继承自某些类的类也是如此尤其是班级.

例如,如果class A(object),class B(A),class C(A),和class D(B, C),然后类MRO DD->B->C->A.B类可能已被写入,可能是,它认为它来自A,当它super()自己调用时,它将在A上获得一个方法.但这不再是真的; 当B调用时super(),它将在C上获得一个方法,如果存在的话.

如果在重写方法中更改方法签名,则可能会出现问题.B类,在调用super时期望A类方法的签名,而是从C获取一个方法,该方法可能没有该签名(从B类的角度来看,可能会也可能不会实现所需的行为).

class A(object):
    def __init__(self, foo):
        print "A!"

class B(A):
    def __init__(self, foo, bar):
        print "B!"
        super(B, self).__init__(foo)

class C(A):
    def __init__(self, foo, baaz):
        print "C!"
        super(C, self).__init__(foo)

class D(B, C):
    def __init__(self, foo, bar):
        print "D!"
        super(D, self).__init__(foo, bar)

print D.mro()
D("foo", "bar")
Run Code Online (Sandbox Code Playgroud)

在此代码示例中,类B和C已合理地扩展了A,并更改了其__init__签名,但正确调用了其预期的超类签名.但是当你像那样做D时,B的有效"超类"变成C而不是A.当它调用超级时,事情就会爆炸:

[<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <type 'object'>]
D!
B!
Traceback (most recent call last):
  File "/tmp/multi_inherit.py", line 22, in <module>
    D("foo", "bar")
  File "/tmp/multi_inherit.py", line 19, in __init__
    super(D, self).__init__(foo, bar)
  File "/tmp/multi_inherit.py", line 9, in __init__
    super(B, self).__init__(foo)
TypeError: __init__() takes exactly 3 arguments (2 given)
Run Code Online (Sandbox Code Playgroud)

对于其他方法也可能发生同样的事情(如果他们调用super()),并且"菱形"不必仅出现在类层次结构的根部.

  • 所有这一切都是正确的,但任何具有多重继承的语言都必​​须处理这些问题.如果我们假设你的答案是正确的,那么什么语言(与MI)*不会*具有有限形式的多重继承? (7认同)

Joh*_*oDo 5

除了@Matt Anderson的回答之外,我认为这些限制实际上适用于旧式类(Python 2.6的教程仍在解决).

在Python 3教程中,文本现在是:Python也支持多重继承的形式.