基本(スーパー)クラスを初期化するにはどうすればよいですか?


125

Pythonでは、次のコードがあるとします。

>>> class SuperClass(object):
    def __init__(self, x):
        self.x = x

>>> class SubClass(SuperClass):
    def __init__(self, y):
        self.y = y
        # how do I initialize the SuperClass __init__ here?

SuperClass __init__サブクラスでを初期化するにはどうすればよいですか?私はPythonチュートリアルに従っていますが、それについては説明していません。Googleで検索したところ、複数の方法が見つかりました。これを処理する標準的な方法は何ですか?

回答:


146

Python(バージョン3まで)は、「古いスタイル」のクラスと新しいスタイルのクラスをサポートしています。新しいスタイルのクラスはobject、あなたが使用しているものから派生したものでありsuper()、を通じてそれらの基本クラスを呼び出します。たとえば、

class X(object):
  def __init__(self, x):
    pass

  def doit(self, bar):
    pass

class Y(X):
  def __init__(self):
    super(Y, self).__init__(123)

  def doit(self, foo):
    return super(Y, self).doit(foo)

Pythonは古いスタイルのクラスと新しいスタイルのクラスを認識しているため、ベースメソッドを呼び出す方法はいくつかあります。

完全を期すために、古いスタイルのクラスは、基本クラスを使用して明示的に基本メソッドを呼び出します。

def doit(self, foo):
  return X.doit(self, foo)

しかし、あなたはもう古いスタイルを使うべきではないので、私はこれについてあまり気にしません。

Python 3は新しいスタイルのクラスのみを認識します(派生クラスかどうかは関係ありobjectません)。


37

両方とも

SuperClass.__init__(self, x)

または

super(SubClass,self).__init__( x )

機能します(DRYの原則に忠実であるため、2つ目の方法をお勧めします)。

こちらをご覧ください:http : //docs.python.org/reference/datamodel.html#basic-customization


8
違う。superは新しいスタイルのクラスでのみ機能し、新しいスタイルのクラスを使用するときにベースを呼び出す唯一の適切な方法です。さらに、古いスタイルのコンストラクトを使用して明示的に「self」を渡す必要もあります。
Ivo van der Wijk

1
@Ivo-OPは例で新しいスタイルのクラスを提供し、誰も古いスタイルを使用する必要がないため、新しいスタイルと古いスタイルの違いについて話すことはほとんど意味がありません。私が(Pythonドキュメントに)提供したリンクは、スーパークラスを呼び出す「適切な」方法が複数あることを示唆してい__init__ます。
adamk


21

基本(スーパー)クラスを初期化するにはどうすればよいですか?

class SuperClass(object):
    def __init__(self, x):
        self.x = x

class SubClass(SuperClass):
    def __init__(self, y):
        self.y = y

superオブジェクトを使用して、メソッド解決順序で次のメソッドを(バインドされたメソッドとして)確実に取得します。Python 2では、クラス名を渡しself、バインドされた__init__メソッドを検索するためにスーパーする必要があります。

 class SubClass(SuperClass):
      def __init__(self, y):
          super(SubClass, self).__init__('x')
          self.y = y

Python 3では、引数をsuper不要にする小さな魔法があります-副次的な利点として、それは少し速く機能します:

 class SubClass(SuperClass):
      def __init__(self, y):
          super().__init__('x')
          self.y = y

以下のように親をハードコーディングすると、協調多重継承を使用できなくなります。

 class SubClass(SuperClass):
      def __init__(self, y):
          SuperClass.__init__(self, 'x') # don't do this
          self.y = y

__init__返さNoneれる可能性があることに注意してください-オブジェクトをインプレースで変更することを目的としています。

何か __new__

インスタンスを初期化する別の方法があります。これは、Pythonの不変型のサブクラスの唯一の方法です。あなたはサブクラスにしたいのであれば、それは必須ですstrか、tupleまたは別の不変オブジェクト。

暗黙のクラス引数を取得するため、それはクラスメソッドであると考えるかもしれません。しかし、それは実際には静的メソッドです。したがって__new__cls明示的にで呼び出す必要があります。

通常はからインスタンスを返す__new__ので、返す場合は、基本クラスで基本の__new__via も呼び出す必要がありsuperます。したがって、両方の方法を使用する場合:

class SuperClass(object):
    def __new__(cls, x):
        return super(SuperClass, cls).__new__(cls)
    def __init__(self, x):
        self.x = x

class SubClass(object):
    def __new__(cls, y):
        return super(SubClass, cls).__new__(cls)

    def __init__(self, y):
        self.y = y
        super(SubClass, self).__init__('x')

Python 3は、__new__静的メソッドであることによって引き起こされるsuper呼び出しの奇妙さを少し回避しますがcls、非バインド__new__メソッドに渡す必要があります。

class SuperClass(object):
    def __new__(cls, x):
        return super().__new__(cls)
    def __init__(self, x):
        self.x = x

class SubClass(object):
    def __new__(cls, y):
        return super().__new__(cls)
    def __init__(self, y):
        self.y = y
        super().__init__('x')
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.