52

私は最近、呼び出す必要がある基本クラスのメソッドを呼び出すことを (StackOverflow 経由で) 発見しました。

super([[derived class]], self).[[base class method]]()

それは結構です、それは動作します。ただし、変更を加えるときにクラス間でコピーして貼り付けることがよくあり、派生クラスの引数を super() 関数に修正するのを忘れることがよくあります。

派生クラスの引数を変更することを忘れないようにしたいと思います。self.__class__代わりに、super() 関数の最初の引数として使用できますか?

動作しているように見えますが、これを行うべきではない正当な理由はありますか?

4

2 に答える 2

88

いいえ、あなたがすることはできません。呼び出しではsuper()、オーバーライドされたメソッドの基本クラスを検索するために、メソッドがどのクラスに属しているかを知る必要があります。

を渡した場合self.__class__(またはさらに良い場合type(self))は、メソッドを検索するための間違ったsuper()開始点が与えられ、最終的に独自のメソッドを再度呼び出すことになります。

メソッド解決順序シーケンスを形成するクラスのリスト内のポインターとして参照してください。渡すとtype(self)、ポインターは元の開始点ではなく、サブクラスを参照します。

次のコードでは、無限再帰エラーが発生します。

class Base(object):
    def method(self):
        print 'original'

class Derived(Base):
    def method(self):
        print 'derived'
        super(type(self), self).method()

class Subclass(Derived):
    def method(self):
        print 'subclass of derived'
        super(Subclass, self).method()

デモ:

>>> Subclass().method()
subclass of derived
derived
derived
derived

<... *many* lines removed ...>

  File "<stdin>", line 4, in method
  File "<stdin>", line 4, in method
  File "<stdin>", line 4, in method
RuntimeError: maximum recursion depth exceeded while calling a Python object

ですので、type(self)ありませんSubclass DerivedDerived.method()

この例では、 の MROSubclass[Subclass, Derived, Base]であり、super()オーバーライドされたメソッドの検索を開始する場所を知る必要があります。youを使用しtype(self)て から開始するように指定すると、次の場所Subclassが検索されますDerived.method()

于 2013-08-13T12:08:48.943 に答える