在python教程中,它说“Python supports a limited form of multiple inheritance”。
有什么限制?
答案 0 :(得分:12)
我不确定python教程的作者所指的是什么限制,但我猜它部分与在python中实现方法/属性查找的方式有关(“方法解析顺序”或MRO)。 Python使用C3 superclass linearization机制;这是为了处理所谓的“The Diamond Problem”。
一旦你在类层次结构中引入了多个继承,任何给定的类都没有它继承的单个潜在类,它只有“MRO中的下一个类”,即使对于期望它们的类也是如此特别从某些类继承。
例如,如果class A(object)
,class B(A)
,class C(A)
和class D(B, C)
,则类D
的MRO为D->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")
在此代码示例中,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)
对于其他方法也可能发生同样的事情(如果他们调用super()
),并且“菱形”不必仅出现在类层次结构的根目录中。
答案 1 :(得分:5)
除了@Matt Anderson的答案之外,我认为这些限制实际上适用于旧式课程(Python 2.6 still addresses的教程)。
在Python 3教程中,文本现在是:Python supports a form of multiple inheritance as well。