Python 多重继承;“破碎的”;钻石
我在探索当两个父类中的一个不从公共基类继承时,多重继承是如何工作的。节目如下:Python 多重继承;“破碎的”;钻石,python,python-3.x,Python,Python 3.x,我在探索当两个父类中的一个不从公共基类继承时,多重继承是如何工作的。节目如下: '''Demomstration of MRO on 'broken' diamonds''' class Base: def hello(self): print('Base') class Left(Base): def hello(self): print('Left') super().hello() class Right: de
'''Demomstration of MRO on 'broken' diamonds'''
class Base:
def hello(self):
print('Base')
class Left(Base):
def hello(self):
print('Left')
super().hello()
class Right:
def hello(self):
print('Right')
super().hello()
class Child1(Left, Right):
'''Class has right edge missing'''
def hello(self):
print('Child1')
super().hello()
class Child2(Right, Left):
'''Class has left edge missing'''
def hello(self):
print('Child2')
super().hello()
print(help(Child1))
print(help(Child2))
print('Child1 output:')
print('==============')
Child1().hello()
print('\nChild2 output:')
print('==============')
Child2().hello()
help()
指出,在第一种情况下,MRO将:
| Child1
| Left
| Base
| Right
| builtins.object
而在第二种情况下(请注意:Right
实际上位于左侧):
但是hello()
函数的输出是:
Child1 output:
==============
Child1
Left
Base
Child2 output:
==============
Child2
Right
Left
Base
因此,在第一种情况下,Right
类被完全跳过!这几乎就像口译员无法接触到它,因为没有任何连接可以跟随
我可以理解,这可以通过使用C3线性化算法来解释,但是层次结构中的一个类被忽略,而镜像情况下则没有,这不是有点奇怪吗?您的
库。hello
函数在这个测试中“被破坏”。考虑你的MRO中的<代码> hello >代码>:
Child1.hello
print('Child1') # PRINTED
super().hello() # super() -> Left
Left.hello
print('Left') # PRINTED
super().hello() # super() -> BASE
Base.hello
print('Base') # PRINTED
# no call to super()!!!
Right.hello # NEVER CALLED
print('Left')
super().hello() # super() -> object
builtins.object.hello
所以基本上,一旦
super().hello
解析为Base.hello
,那么super
链就停止了<代码>基本。hello错过了对super
的调用,无法前进到Right
。因此,Right.hello
不会被调用,即使Right
在MRO中。您的Base.hello
函数在该测试中“已损坏”。考虑你的MRO中的<代码> hello >代码>:
Child1.hello
print('Child1') # PRINTED
super().hello() # super() -> Left
Left.hello
print('Left') # PRINTED
super().hello() # super() -> BASE
Base.hello
print('Base') # PRINTED
# no call to super()!!!
Right.hello # NEVER CALLED
print('Left')
super().hello() # super() -> object
builtins.object.hello
所以基本上,一旦
super().hello
解析为Base.hello
,那么super
链就停止了<代码>基本。hello错过了对super
的调用,无法前进到Right
。因此,Right.hello
不会被调用,即使Right
在MRO中。您使用的是python2还是python3?在蟒蛇3中没有“碎钻石”。你总是把对象
放在上面,所以最后总会有一颗钻石。但是,如果您使用的是python2,那么您使用的是不推荐使用的旧式类,而且不使用C3线性化。您可以从帮助中看到MRO中的问题:Base
位于Right
之前,但不调用super().hello()
@dotslash。。。那么<代码>打印(“Hello”)
是有效的python2,并且打印的内容与python3中的内容完全相同。应该让我意识到它是python3的东西是在旧式类中调用super
,而且super
没有参数。@dotslash按照这个顺序,直到它到达基。hello
,它不调用super
。所以就到此为止。“几乎就像解释器无法接触到它,因为没有要遵循的连接”-不,因为代码没有告诉它要遵循连接!在python2中,()
不是函数调用的一部分,它们只是对不起任何作用的括号进行分组。与编写x=(5)
相同,这与x=5
相同。此更改适用于打印(1,2)
。在python3中,它生成12
,因为它是一个带有两个参数的函数调用;在python2中,它生成(1,2)
,因为它只打印元组。然而,在代码中,您总是使用单个参数。您使用的是python2还是python3?在蟒蛇3中没有“碎钻石”。你总是把对象
放在上面,所以最后总会有一颗钻石。但是,如果您使用的是python2,那么您使用的是不推荐使用的旧式类,而且不使用C3线性化。您可以从帮助中看到MRO中的问题:Base
位于Right
之前,但不调用super().hello()
@dotslash。。。那么<代码>打印(“Hello”)
是有效的python2,并且打印的内容与python3中的内容完全相同。应该让我意识到它是python3的东西是在旧式类中调用super
,而且super
没有参数。@dotslash按照这个顺序,直到它到达基。hello
,它不调用super
。所以就到此为止。“几乎就像解释器无法接触到它,因为没有要遵循的连接”-不,因为代码没有告诉它要遵循连接!在python2中,()
不是函数调用的一部分,它们只是对不起任何作用的括号进行分组。与编写x=(5)
相同,这与x=5
相同。此更改适用于打印(1,2)
。在python3中,它生成12
,因为它是一个带有两个参数的函数调用;在python2中,它生成(1,2)
,因为它只打印元组。然而在你的代码中你总是使用一个参数。接下来的问题是:如果你只是盲目地在Base
中使用super
,有时你最终会调用对象。你好
,结果很糟糕@我刚刚遇到了这样的事情!在base中粘贴super()
到达右侧
,然后抛出AttributeError
,因为我想,现在树已经被遍历了,没有更多的super()
了。我在哪里可以找到一些关于使用super()
的指南?@jornsharpe我希望你能推荐一些博客文章,不过还是谢谢你@dotslash是经典之作,你可以通过…@jornsharpe找到它。我知道这篇文章/演讲,但认为它对像我这样的傻瓜没有帮助P:我去看看。谢谢后续问题:如果你只是在Base
中盲目地super
,有时你最终会调用对象。你好
,结果是灾难性的@我刚刚遇到了这样的事情!在base中粘贴super()
到达右侧
,然后抛出AttributeError
,因为我猜,现在树已经被遍历,t