2017-02-14 9 views
0

最近私は本を読んでいる、それは多重継承でMROを言及し、サンプルコードを与える:のpython多重継承出力問題

class A(object): 
    def __init__(self): 
     print "A" 
     super(A, self).__init__() 

class B(object): 
    def __init__(self): 
     print "B" 
     super(B, self).__init__() 

class C(A,B): 
    def __init__(self): 
     print "C" 
     A.__init__(self) 
     B.__init__(self) 

C() 

出力:

C 
A 
B 
B 

私がなぜこの知りたいです起こる?

答えて

2

あなたはsuper経由で直接コンストラクタの呼び出しと呼び出しを混合しているためです。クラス階層はどちらか一方を行う必要があります。

より正確には、クラスCのMROはC, A, Bです。したがって、あなたはBCのMROでAを成功以来、Bのコンストラクタを呼び出し、Aのコンストラクタにsuper(A, self).__init__()を呼び出すとき。つまり、最初のBが印刷されるのはAのコンストラクタの内側です。

これ以外にも、super(A, self)の書き出しはPython 3では余計です。super()で十分です。引数はコンテキストからdeducedです。

さらに読書:

0

私は(print()printを変更することで)のpython3にあなたのコードに変換し、いくつかのより多くのトレースステートメントを追加しました:

class A(object): 
    def __init__(self): 
     print("A", type(self).__mro__) 
     super(A, self).__init__() 
     print("/A") 

class B(object): 
    def __init__(self): 
     print("B", type(self).__mro__) 
     super(B, self).__init__() 
     print("/B") 

class C(A,B): 
    def __init__(self): 
     print("C") 
     A.__init__(self) 
     print("ca/b") 
     B.__init__(self) 
     print("/C") 

C() 

がここに出力です:

出力を見てみると
C 
A (<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>) 
B (<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>) 
/B 
/A 
ca/b 
B (<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>) 
/B 
/C 

、あなたはC.__init__メソッドの呼び出しが起こって、および「C」を印刷して確認することができます。次にA.__init__を直接呼び出します(これは間違いですsuper!)。

A.__init__コールは__mro__属性を含めてそのメッセージを、表示します。シーケンスはC→A→B→Objectの順で見ることができます。それはA.__init__内からsuper()への呼び出しは、クラスBを参照しようとしていることを意味するので、これは重要です。また、あなたがそれらを許可すれば、自動的にA.__init__を呼び出しているだろうC.__init__内側からsuperに呼び出します。

B.__init__は、前述のようにA.__init__内のsuper参照によって呼び出されます。恐らくObject.__init__が呼び出され、何も印刷されません。 ;-)

両方B.__init__A.__init__リターン、我々は中間メッセージca/bを参照して、B.__init__への直接呼び出しが行われます。メッセージを出力しますが、superフォームB.__init__への参照は何も行いません。BはMROの末尾にあるためです。

super()メカニズムは、このMROのすべてのものを処理できます。 A.__init__(self)を呼び出す必要はありません。とても素晴らしいことだ

class C(A,B): 
    def __init__(self): 
     print("C") 
     super(C, self).__init__() 
+0

:代わりに、あなただけsuperハンドルを、C.__init__内部が、これをやってみましょうことができます!ありがとうございました – TreeCatCat