2013-01-07 11 views
33

Pythonでは、どの親メソッドを呼び出すのかを選択するにはどうすればよいですか?親ASDF2の__init__メソッドを呼び出したいとします。私はASDF1をsuper()..で指定しなければならないようですね。 ASDF3の__init__と呼ぶ場合は、ASDF2を指定する必要があります。Pythonの多重継承:呼び出すsuper()の選択

>>> class ASDF(ASDF1, ASDF2, ASDF3): 
    def __init__(self): 
     super(ASDF1, self).__init__() 


>>> ASDF() 
ASDF2's __init__ happened 
>>> class ASDF(ASDF1, ASDF2, ASDF3): 
    def __init__(self): 
     super(ASDF2, self).__init__() 


>>> ASDF() 
ASDF3's __init__ happened 

私にとっては思われます。私は間違って何をしていますか?

答えて

47

これは、super()が対象ではありません。スーパーは、基本的に特定の順序で親の1つ(またはすべて)を選択します。あなたは、単一の親のメソッドを呼び出したい場合は、この

class ASDF(ASDF1, ASDF2, ASDF3): 
    def __init__(self): 
     ASDF2.__init__(self) 
10

superは、メソッド解決順で次のメソッドを呼び出してください。線形継承ツリーでは、すぐ親クラスからのメソッドになります。

ここでは3つの親があり、次の__init__の方法はASDF1の観点からはASDF2です。一般的に、安全なことは、何か他のことをしたい理由がわからない限り、継承リストの最初のクラスをsuperに渡すことです。

どのような点が明示的に呼び出す必要がありますか?__init__を呼び出す必要があります。ここでの質問は、スーパークラス__init__メソッドのすべてを呼びたくない理由です。

superをPythonで使用することに関するかなりの文献があります。トピックをGoogleでグーグルで検索し、結果を読むことをおすすめします。

4

super()の最初の引数としてASDF1(親クラスの1つ)を渡しています。それをしないでください。代わりに、super()の最初の引数としてASDFを渡す必要があります。

Python 2.7 documentation for super()

は、Python 2.7ドキュメントを引用すると、典型的なスーパークラスの呼び出しは次のようになります。最初の引数は、スーパーここに現在のクラスであるC、であるために

class C(B): 
    def method(self, arg): 
     super(C, self).method(arg) 

ていることに注意してください。 B(親クラス)をsuper()に渡さないでください。

メソッド解決順序(MRO)を決定するとき、スーパーは最初の引数として渡されたクラスをスキップし、そのクラスの親と兄弟を調べ始めます。したがって、super()の最初の引数としてASDF1を渡すと、ASDF1をスキップしてASDF2で検索を開始しました。だからASDF2の__init__が呼ばれたのです。


Python 3では、現在のクラスをもう渡す必要はありません。

class C(B): 
    def method(self, arg): 
     super().method(arg) # This does the same thing as: 
           # super(C, self).method(arg) 
           # (Python 3 only)