web-dev-qa-db-ja.com

Python:スーパークラス__init__を継承します

多くの___init___引数を持つ基本クラスがあります。

_def BaseClass(object):
    def __init__(self, a, b, c, d, e, f, ...):
        self._a=a+b
        self._b=b if b else a
        ...
_

すべての継承クラスは、基本クラスの___init___メソッドを実行する必要があります。

スーパークラス___init___を呼び出す継承クラスのそれぞれに__init__()メソッドを記述できますが、これは深刻なコードの重複になります。

_def A(BaseClass):
    def __init__(self, a, b, c, d, e, f, ...):
        super(A, self).__init__(a, b, c, d, e, f, ...)

def B(BaseClass):
    def __init__(self, a, b, c, d, e, f, ...):
        super(A, self).__init__(a, b, c, d, e, f, ...)

def C(BaseClass):
    def __init__(self, a, b, c, d, e, f, ...):
        super(A, self).__init__(a, b, c, d, e, f, ...)

...
_

スーパークラス___init___を自動的に呼び出す最もPython的な方法は何ですか?

55
Adam Matan
super(SubClass, self).__init__(...)

変数の悪夢の解決に役立つ場合は、* argsと** kwの使用を検討してください。

48
Andreas Jung

明示的に記述する必要がありますが、一方で、多くの引数がある場合は、おそらく位置引数には* argsを、キーワード引数には** kwargsを使用する必要があります。

class SubClass(BaseClass):
    def __init__(self, *args, **kwargs):
        super(SubClass, self).__init__(*args, **kwargs)
        # SubClass initialization code

使用できる別の手法は、initのコードを最小化し、init関数の最後に別のカスタム関数を呼び出すことです。次に、サブクラスで、カスタム関数をオーバーライドするだけです

class BaseClass(object):
    def __init__(self, *args, **kwargs):
        # initialization code
        self._a = kwargs.get('a')
        ...
        # custom code for subclass to override
        self.load()

    def load():
        pass

class SubClass(BaseClass)
    def load():
        # SubClass initialization code
        ...
32
Ryan Ye

派生クラスが基本クラス__init__()が既に行うことを超えて実装しない場合、派生クラス__init__()メソッドを省略します-基本クラス__init__()は自動的に呼び出されます。

OTOHで、派生クラスが__init__()に余分な作業を追加し、基本クラス__init__()を明示的に呼び出さないようにするには、次のようにします。

_class BaseClass(object):
    def __new__(cls, a, b, c, d, e, f, ...):
        new = object.__new__(cls)
        new._a=a+b
        new._b=b if b else a
        ...
        return new

class A(BaseClass):
    ''' no __init__() at all here '''

class B(BaseClass):
    def __init__(self, a, b, c, d, e, f, ...):
        ''' do stuff with init params specific to B objects '''
_

__new__()は常に自動的に呼び出されるため、派生クラスでこれ以上の作業は必要ありません。

18
pillmuncher

サブクラスの__init__()メソッドで何か便利なことをしているのでなければ、オーバーライドする必要はありません。

def BaseClass(object):
    def __init__(self, a, b, c, d, e, f, ...):
        self._a=a+b
        self._b=b if b else a
        ...

def A(BaseClass):
    def some_other_method(self):
        pass

def B(BaseClass):
    pass
14
Rob Cowie

おそらくあなたの場合のより明確な実装は、次のように派生クラスで** kwargs 新しい追加の引数と組み合わせてを使用することです:

class Parent:
    def __init__(self, a, b, c):
        self.a = a
        self.b = b
        self.c = c


class Child(Parent):
    def __init__(self, d, **kwargs):
        super(Child, self).__init__(**kwargs)
        self.d = d

この方法により、コードの重複は避けられますが、派生クラスに暗黙的に引数が追加されます。

6
avielbl

基本クラスからinitを継承する2.6以前のバージョンでは、スーパー関数はありません。以下の方法で継承できます。

class NewClass():
     def __init__():
         BaseClass.__init__(self, *args)
2
Aashutosh jha

Pythonic実装を追加します。すべての属性を渡す必要がある場合、以下のコードを使用できます。 (サブセットが必要な場合は、特定のkwargsキーを保持/削除することもできます)。

def A(BaseClass):
    def __init__(self, *args, **kwargs):
        for key, value in kwargs.items():
            setattr(self, key, value)

base = BaseClass(...)
new = A( **base.__dict__ )
0
Ben