262

class A:
 def __init__(self):
   print "world"

class B(A):
 def __init__(self):
   print "hello"

B()
hello

私がスーパーコンストラクタで作業した他のすべての言語では、暗黙のうちに呼び出されます。 Pythonでそれを呼び出す方法は?私は期待するsuper(self)しかしこれはうまくいきません。


6 답변


270

super()親のようなオブジェクトを返します新しいスタイルのクラスで

class A(object):
    def __init__(self):
        print "world"

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

B()


  • 好奇心だけの理由super(B,self)言及されるためにBと自己の両方が必要ですか?これは冗長ではありませんか。自分自身にBへの参照が含まれていてはいけませんか。 - Mike
  • いいえ、なぜならself実際にはのインスタンスかもしれませんCの子B。 - Ignacio Vazquez-Abrams
  • @Luc:これは、クラスが誤って宣言されたためです。私の答えを見てください。 - Ignacio Vazquez-Abrams
  • への敬意を持ってのドキュメンテーションsuper()、あなたは書くことができるはずですsuper().__init__()引数はありません。 - JojOatXGME
  • @ JojOatXGME:3.xでは、はい。 2.xにはまだ引数が必要です。 - Ignacio Vazquez-Abrams

160

他の答えに沿って、スーパークラスメソッド(コンストラクタを含む)を呼び出す方法は複数ありますが、Python-3.xではプロセスが単純化されています。

Python-2.x

class A(object):
 def __init__(self):
   print "world"

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

Python-3.x

class A(object):
 def __init__(self):
   print("world")

class B(A):
 def __init__(self):
   print("hello")
   super().__init__()

super()今では同等ですsuper(<containing classname>, self)に従ってドキュメント


50

Python 2.xの旧式のクラスではこれは次のようになります。

class A: 
 def __init__(self): 
   print "world" 

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


  • これは新しいスタイルクラスでは機能しませんか。 - kdbanman
  • @kdbanman:これは新しいスタイルのクラスでも動作しますが、新しいスタイルのクラスを使用する理由の1つは、このようにしなくてもよいことです。あなたが使用することができますsuperまた、継承元のクラスに直接名前を付ける必要はありません。 - Gabe

32

一つの方法はAのコンストラクタを呼び出して渡すことですself引数として、のように:

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

このスタイルの利点は、とても明確だということです。それはAのコンストラクタを呼び出します。欠点は、共有基本クラスのコンストラクタを2回呼び出すことになる可能性があるため、ひし形の継承をうまく処理できないことです。

他の方法は、他の人が示しているように、super()を使うことです。単一継承の場合、それは基本的に親のコンストラクタを呼ばせるのと同じことをします。

しかし、super()は内部ではかなり複雑で、複数の継承状況では直感的に理解できないことがあります。プラス面では、super()を使用して菱形の継承を処理できます。あなたがsuper()が何をするのかについての重要性を知りたければ、super()がどのように機能するかについて私が見つけた最も良い説明はここに(私は必ずしもその記事の意見を支持するわけではないが)。


  • 引数として(selfを無視して)変数を受け取らない場合、このようにAのコンストラクタを呼び出す必要はありますか。私はコードがなくてもうまく動作することを意味しますA.__init__(self)ライン。 - Red Floyd

2

私は前の答えを拡張する次の公式を使います。

class A(object):
 def __init__(self):
   print "world"

class B(A):
 def __init__(self):
   print "hello"
   super(self.__class__, self).__init__()

B()

こうすることで、呼び出しでクラスの名前を繰り返す必要がなくなりますスーパー。大量のクラスをコーディングしていて、コンストラクターメソッド内のコードをクラス名とは無関係にしたい場合に便利です。


  • しかし、拡張することにした場合、あなたは不定再帰を得るでしょうBC、そしてself.__class__に指差すC(B)の代わりにB(A)、 そうsuper(self.__class__, self)戻るBの代わりにA。 - dened
  • サブクラス化すると、無限再帰エラーになります。B。行うではないつかいますself.__class__またはtype(self)明示的なクラスを渡します(Bこちら)または、Python 3では、super()引数なしで。 - Martijn Pieters

2

短い答え

super(DerivedClass, self).__init__()

長い答え

なにがsuper()行う?

指定されたクラス名を取り、その基本クラスを見つけ(Pythonは多重継承を許します)、そしてメソッドを探します(__init__この場合)左から右へそれらのそれぞれで。利用可能なメソッドが見つかるとすぐにそれを呼び出して検索を終了します。

すべての基本クラスのinitを呼び出すにはどうすればいいですか?

基本クラスが1つしかない場合は上の例がうまくいきます。しかし、Pythonでは多重継承が許可されているため、すべての基本クラスが正しく初期化されていることを確認することをお勧めします。そのためには、各基本クラスにinitを呼び出す必要があります。

class Base1:
  def __init__():
    super(Base1, self).__init__()

class Base2:
  def __init__():
    super(Base2, self).__init__()

class Derived(Base1, Base2):
  def __init__():
    super(Derived, self).__init__()

initをsuperの呼び出しに忘れた場合はどうすればいいですか?

__init__基本クラスは呼び出されません。 C ++やJavaのような暗黙のコンストラクタ呼び出しはありません。

リンクされた質問


関連する質問

最近の質問