super()
DRY (Don't Repeat Yourself) 原則に違反しないように、新しいマジック動作が追加されました。 PEP 3135を参照してください。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 は Guido によって開始されました。Guido は当初super
、キーワードになることを想定しており、セルを使用して現在のクラスを検索するというアイデアも彼のものでした。確かに、これをキーワードにするというアイデアは、PEP の最初のドラフトの一部でした。
しかし、実際には Guido 自身が「あまりにも魔法的」というキーワードのアイデアから離れ、代わりに現在の実装を提案しました。彼は、別の名前を使用すると問題が発生する可能性があると予想しました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