super()
DRY(Do n't Repeat Yourself)の原則に違反しないように、新しい魔法の動作が追加されました。PEP3135を参照してください。クラスをグローバルとして参照することによってクラスに明示的に名前を付ける必要がある場合も、super()
それ自体で発見したのと同じ再バインドの問題が発生しやすくなります。
class Foo(Bar):
def baz(self):
return super(Foo, self).baz() + 42
Spam = Foo
Foo = something_else()
Spam().baz() # liable to blow up
同じことがクラスデコレータの使用にも当てはまり、デコレータはクラス名を再バインドする新しいオブジェクトを返します。
@class_decorator_returning_new_class
class Foo(Bar):
def baz(self):
# Now `Foo` is a *different class*
return super(Foo, self).baz() + 42
マジックsuper()
__class__
セルは、元のクラスオブジェクトにアクセスできるようにすることで、これらの問題をうまく回避します。
PEPは、最初super
はキーワードになることを構想していたグイドによって開始されました。現在のクラスを検索するためにセルを使用するという考えも彼のものでした。確かに、それをキーワードにするという考えは、PEPの最初の草案の一部でした。
しかし、実際にはキーワードのアイデアから「あまりにも不思議」と離れ、現在の実装を提案したのは実際にはグイド自身でした。に別の名前を使用するとsuper()
問題が発生する可能性があると予想していました。
私のパッチは中間ソリューション__class__
を使用しています'super'
。という名前の変数を使用する場合は常に必要であると想定しています。したがって、(全体的に)に名前super
を変更しsupper
て使用するsupper
が、を使用しない場合super
、引数なしでは機能しません(ただし、引数__class__
または実際のクラスオブジェクトを渡すと機能し
ます)という名前の無関係な変数がある場合、問題はありませんsuper
が、メソッドはセル変数に使用されている少し遅い呼び出しパスを使用します。
結局、super
キーワードを使用するのは正しくないと感じ、魔法の__class__
セルを提供することは許容できる妥協であると宣言したのは、グイド自身でした。
実装の魔法の暗黙の動作はいくぶん驚くべきことですがsuper()
、言語で最も不適切に適用された関数の1つであることに同意します。 インターネットで見つかった誤用super(type(self), self)
やsuper(self.__class__, self)
呼び出しのすべてを見てください。そのコードのいずれかが派生クラスから呼び出された場合、無限再帰例外が発生します。少なくとも、super()
引数なしの単純化された呼び出しは、その問題を回避します。
名前が変更されたのはsuper_
; __class__
メソッドでも参照するだけで、再び機能します。あなたはどちらかの参照している場合、セルが作成されsuper
たり __class__
、あなたの方法で名前を:
>>> super_ = super
>>> class A(object):
... def x(self):
... print("No flipping")
...
>>> class B(A):
... def x(self):
... __class__ # just referencing it is enough
... super_().x()
...
>>> B().x()
No flipping