super()处理多重继承不一致



我有两个多重继承的例子,看起来是一样的,但我得到了不同的结果顺序。

Joël的第一个例子:

class A(object):
    def t(self):
        print 'from A'
class B(object):
    def t(self):
        print 'from B'
class C(A): pass
class D(C, B): pass

因此,我们有:

>>> d = D()
>>> d.t() # Will print "from A"
>>> D.__mro__
(<class '__main__.D'>, <class '__main__.C'>, <class '__main__.A'>, 
<class '__main__.B'>, <type 'object'>)

然后在木卫四的第二个例子中:

class First(object):
    def __init__(self):
        print "first"
class Second(First):
    def __init__(self):
        print "second"
class Third(First):
    def __init__(self):
        print "third"
class Fourth(Second, Third):
    def __init__(self):
        super(Fourth, self).__init__()
        print "that's it"

因此,我们有:

>>> f = Fourth()
second
that's it
>>> Fourth.__mro__
(<class '__main__.Fourth'>, <class '__main__.Second'>, <class '__main__.Third'>
<class '__main__.First'>, <type 'object'>)

正如你所看到的,MRO的流动顺序是不同的,在第二个例子中,它在Third之前没有到达First,但在第一个例子中它在到达B之前经过A

没有不一致的地方。MRO基于C3算法,Chaturvedi对此进行了解释,Simionato对此进行了更正式的解释。


关于:

在第二个例子中,它在第三个之前没有达到第一个,但在第一个例子,它在去B之前经过A。

由于Third是由定义的

class Third(First):

Third必须显示在MRO中的First之前。

查图维迪用规则解释了这一点

如果A是B的超类,那么B优先于A。或者,B应该在所有__mro__(同时包含两者(中,始终出现在A之前。

而在第一示例中,FirstThird的等价物是AC。由于C是由定义的

class C(A):

在MRO中,CCD_ 15位于CCD_ 16之前。

为什么A先于B更为复杂。这最终是由于在D的基础上,C被列在B之前。在Simionato的记法中,

L[D] = L[D(C,B)] = D + merge(L[C], L[B], CB)
     = D + merge(CAO, BO, CB)
     = D + C + merge(AO, BO, B)
     = D + C + A + merge(O, BO, B)
     = D + C + A + B + merge(O, O)
     = D + C + A + B + O

在第二个例子中,

L[4] = L[4(2, 3)] = 4 + merge(L[2], L[3], 23)
     = 4 + merge(21O, 31O, 23)
     = 4 + 2 + merge(1O, 31O, 3)
     = 4 + 2 + 3 + merge(1O, 1O)    # Third must come before First
     = 4 + 2 + 3 + 1 + merge(O, O)
     = 4 + 2 + 3 + 1 + O

操作规则为:

取第一个列表的头,即L[B1][0]如果此头不在任何其他列表的尾部,则将其添加到线性化的,并将其从合并中的列表中删除,否则请查看排在下一个名单的首位,如果是好的话,就拿下它。然后重复操作,直到所有类都被删除,或者不可能找到好的头脑。在这种情况下,不可能构建merge,Python 2.3将拒绝创建类C,并将引发例外

(我的重点解释了为什么Third必须在First之前(。

这不一样,在第一个例子中,所有"dad"对象都继承对象,因为D加载C,C加载A,按照MRO的顺序,B(由D调用(

在第二个例子中,所有"dad"对象都继承了类First。此时,Python最后加载First,因为它需要处理Second和Third。

附言:这是我的理论,但这只是逻辑。

以下是您在他的示例中实现的一个运行示例:http://ideone.com/pfzXiG

class First(object):
    def __init__(self):
        print "first"
class Second(First):
    def __init__(self):
        print "second"
class Third(First):
    def __init__(self):
        print "third"
class Fourth(Second, Third):
    def __init__(self):
        super(Fourth, self).__init__()
        print "that's it"
print "First: "
print Fourth.__mro__
class First(object):
    def __init__(self):
        print "first"
class Second(object):
    def __init__(self):
        print "second"
class Third(First):
    def __init__(self):
        print "third"
class Fourth(Third, Second):
    def __init__(self):
        super(Fourth, self).__init__()
        print "that's it"
print "Second:"
print Fourth.__mro__

您的第一个继承继承体系如下所示:

D
|
C B
| |
A |
 |
   object

而你的第二个是:

4
|
2 3
 |
  1
  |
  object

为什么在第二示例中它没有在Third之前到达First,而在第一示例中它在到达B之前经过A

你为什么期望这些人也有同样的行为?从图中可以看出,AB之间的关系与FirstThird之间的关系完全不同。

最新更新