0

我有两个看起来相同的多重继承示例,但我得到的结果顺序不同。

乔尔第一个例子

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'>)

然后在Callisto的第二个示例中:

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不同,在第二个示例中它没有到达First之前,Third但在第一个示例中它在到达之前A经过B

4

3 回答 3

3

没有不一致。MRO 基于 C3 算法,该算法由Chaturvedi解释,更正式地由Simionato 解释


关于:

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

由于Third定义为

class Third(First):

Third必须出现First在 MRO 之前。

Chaturvedi 用规则解释了这一点,

如果 A 是 B 的超类,则 B 优先于 A。或者,在所有__mro__s(包含两者)中,B 应始终出现在 A 之前。

而在第一个示例中, and 的等价FirstThirdAand C。由于C定义为

class C(A):

C在 MRO之前A

为什么A在前面B更复杂。归根结底是因为C之前BD. 在 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];如果此头部不在任何其他列表的尾部,则将其添加到 C 的线性化中,并将其从合并中的列表中删除,否则查看下一个列表的头部并将其取出,如果它是好头。然后重复这个操作,直到所有的类都被移除或者不可能找到好的磁头。在这种情况下,无法构造合并,Python 2.3 将拒绝创建 C 类并引发异常。

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

于 2013-04-23T18:17:37.500 回答
0

不一样,在第一个示例中,所有“爸爸”对象都继承对象,因为 D 加载加载 A 的 C,并且按照 MRO 的顺序,B(由 D 调用)

其次,所有“爸爸”对象都继承了 First 类。此时,Python 会在最后加载 First,因为它需要处理 Second 和 Third。

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

这是您在他的示例中实现的运行示例: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__
于 2013-04-23T18:24:56.860 回答
-1

您的第一个继承层次结构如下所示:

D
|\
C B
| |
A |
 \|
   object

而你的第二个是:

4
|\
2 3
 \|
  1
  |
  object

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

为什么你会期望它们的行为方式相同?看图表,和之间的关系与和A之间的关系B完全不同FirstThird

于 2013-04-23T18:18:29.693 回答