9

私はPythonで多重継承をいじっていましたが、それがどのように発生するのか理解できない状況に遭遇しました。

継承のレイアウトは次のとおりです。

    A       F
  /   \     |
 B     C    |   
  \    |   /
    \  |  /   
       D

誰もが知っているABCDダイヤモンド。さらに、追加のクラス「F」を追加して楽しみます。

コードは次のとおりです。

class A(object):
    def foo(self, call_from):
        print "foo from A, call from %s" % call_from
        super(A, self).foo("A")

class B(A):
    def foo(self, call_from):
        print "foo from B, call from %s" % call_from
        super(B, self).foo("B")

class C(A):
    def foo(self, call_from):
        print "foo from C, call from %s" % call_from
        super(C, self).foo("C")

class F(object):
    def foo(self, call_from):
        print "foo from F, call from %s" % call_from

class D(B, C, F):
    def foo(self):
        print "foo from D"
        super(D, self).foo("D")

出力:

>>> d = D()
>>> d.foo()
foo from D
foo from B, call from D
foo from C, call from B
foo from A, call from C
foo from F, call from A

メソッドの解決順序:

>>> D.__mro__
(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class '__main__.F'>, <type 'object'>)
  • foo from C, call from Bそれ以外のfoo from C, call from D
  • foo from F, call from Aただ私を捨てるだけです...

super()メソッドの解決順序に従って連鎖し、クラス間の関係を無視しているように見えますが、よくわかりません。

誰かが私にこの行動を理解するための正しい方向を示すことができますか?

私は言語自体を理解しようとしていることを覚えておいてください。実用的な問題を解決しようとはしていません。したがって、これのユースケースはありません。しかし、誰かがユースケースを指摘できればいいでしょう:)


アップデート:

要約すると、super()は、mroのベースを呼び出す次の項目を通知するだけです。親である必要はありません。mroは継承階層に基づいて構築されていますが、mro自体は継承階層ではありません。

4

2 に答える 2

8

の要点はsuper()、メソッドの解決順序に従うことです。そのため、親クラスではなく、独自のクラスを指定します。プログラマーが次に呼び出されるクラスを予測するのは難しいので、あなたsuper()がそれを処理します。

すでにDからBが呼び出されているのに、どうすればDからCを呼び出すことができますか?D.foo()は、他のfoo()を1つしか呼び出すことができません。これは、関数呼び出しが1つしかないためです。これは呼び出しの線形チェーンになるため、クラスを線形化する必要があります。これは、メソッドの解決順序が行うことです。

于 2012-07-06T01:43:08.927 に答える
1

親クラスでsuperを呼び出すと便利な場合があります。元。

class TmpClass0(object):
    def tmp_method(self):
        print 'TmpClass0 tmp_method'

class TmpClass1(TmpClass0):
    def tmp_method(self):
        print 'TmpClass1 tmp_method'

ここで、TmpClass2のインスタンスからTmpClass0のtmp_methodを使用したいと思います。

class TmpClass2(TmpClass1):                                                                               
    def tmp_method(self):
        super(TmpClass1, self).tmp_method()

結果:

In [107]: tmp_class2 = TmpClass2()                                                                                  

In [108]: tmp_class2.tmp_method()                                                                                   
TmpClass0 tmp_method
于 2014-12-09T20:36:57.943 に答える