0

同じように見える多重継承の 2 つの例がありますが、結果の順序が異なります。

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

次にCallistoの2 番目の例では:

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

ご覧のとおり、 のフロー順序が異なり、2 番目の例では前にMRO到達しませんが、1 番目の例ではに行く前に通過します。FirstThirdAB

4

3 に答える 3

3

矛盾はありません。MRO は、 Chaturvediによって説明され、より正式にはSimionatoによって説明された C3 アルゴリズムに基づいています。


それにかんする:

2 番目の例では、3 番目の前に First に到達しませんが、最初の例では、B に行く前に A を通過します。

Thirdによって定義されているため、

class Third(First):

ThirdFirstMRO の前に表示する必要があります。

チャトゥルヴェーディはこれをルールで説明しています。

A が B のスーパークラスである場合、B は A よりも優先されます。または、B は常にすべて__mro__の s (両方を含む) で A の前に表示される必要があります。

First最初の例では、 andに相当するのThirdAandCです。Cによって定義されているため、

class C(A):

CAMRO で優先されます。

なぜA前に来るのかBはもっと複雑です。最終的には のベースでC以前にリストされているためです。Simionato の記法では、BD

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

そして2番目の例では、

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 に答える