私は最近、(StackOverflowを介して)基本クラスのメソッドを呼び出すために呼び出す必要があることを発見しました。
super([[derived class]], self).[[base class method]]()
それは結構です、それは動作します。ただし、変更を加えると、クラス間でコピーと貼り付けを頻繁に行い、派生クラスの引数をsuper()関数に修正するのを忘れることがよくあります。
派生クラスの引数を変更することを忘れないようにしたいのですが。代わりにself.__class__
super()関数の最初の引数として?
それはうまくいくようですが、私がこれをしてはいけない理由はありますか?
いいえ、あなたがすることはできません。オーバーライドされたメソッドの基本クラスを検索するには、super()
呼び出しでメソッドがどのクラスに属しているかを知る必要があります。
_self.__class__
_(さらに良いのはtype(self)
)を渡すと、super()
にwrongメソッドを検索するための開始点であり、最終的に独自のメソッドを再度呼び出します。
メソッド解決順序シーケンスを形成するクラスのリスト内のポインタとして参照してください。 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
であるため、_notDerived
、Derived.method()
になります。
この例では、Subclass
のMROは_[Subclass, Derived, Base]
_であり、super()
はオーバーライドされたメソッドの検索を開始する場所を知る必要があります。 type(self)
を使用して、Subclass
から開始するように指示すると、次にDerived.method()
が見つかります。
self.__class__
かもしれませんnotはサブクラスですが、むしろ孫以下のクラスであり、スタック破壊ループにつながります。