super()Dodano nowe magiczne zachowanie, aby uniknąć naruszenia zasady SUCHY (nie powtarzaj się), patrz PEP 3135 . Konieczność jawnego nazwania klasy przez odwołanie się do niej jako globalnej jest również podatna na te same problemy z ponownym wiązaniem, które odkryłeś z super()samą sobą:
class Foo(Bar):
def baz(self):
return super(Foo, self).baz() + 42
Spam = Foo
Foo = something_else()
Spam().baz() # liable to blow up
To samo dotyczy używania dekoratorów klas, w których dekorator zwraca nowy obiekt, który ponownie wiąże nazwę klasy:
@class_decorator_returning_new_class
class Foo(Bar):
def baz(self):
# Now `Foo` is a *different class*
return super(Foo, self).baz() + 42
Magiczna super() __class__komórka ładnie omija te problemy, dając ci dostęp do oryginalnego obiektu klasy.
PEP został zapoczątkowany przez Guido, który początkowo wyobrażał sobie, że superzostanie słowem kluczowym , a pomysł wykorzystania komórki do wyszukania aktualnej klasy był również jego . Z pewnością pomysł uczynienia go słowem kluczowym był częścią pierwszego projektu PEP .
Jednak w rzeczywistości to sam Guido odszedł od pomysłu słowa kluczowego jako „zbyt magiczny” , proponując zamiast tego obecną implementację. On Przewiduje się, że przy użyciu innej nazwy super()może być problem :
Moja łatka używa rozwiązania pośredniego: zakłada, że potrzebujesz, __class__
gdy używasz zmiennej o nazwie 'super'. Tak więc, jeśli (globalnie) zmienisz nazwę superna supperi użyjesz, supperale nie super, to nie będzie działać bez argumentów (ale nadal będzie działać, jeśli przekażesz go
__class__lub rzeczywisty obiekt klasy); jeśli masz nazwaną niepowiązaną zmienną super, wszystko będzie działać, ale metoda użyje nieco wolniejszej ścieżki wywołania używanej dla zmiennych komórki.
W końcu to sam Guido ogłosił, że użycie supersłowa kluczowego nie wydaje się właściwe, a zapewnienie magicznej __class__komórki jest akceptowalnym kompromisem.
Zgadzam się, że magiczne, ukryte zachowanie implementacji jest nieco zaskakujące, ale super()jest jedną z najczęściej niewłaściwie stosowanych funkcji w języku. Wystarczy spojrzeć na wszystkie niewłaściwie zastosowane super(type(self), self)lub super(self.__class__, self) inwokacje znalezione w Internecie; gdyby którykolwiek z tych kodów był kiedykolwiek wywołany z klasy pochodnej , skończyłoby się to z nieskończonym wyjątkiem rekursji . Przynajmniej uproszczone super()wywołanie, bez argumentów, pozwala uniknąć tego problemu.
Co do przemianowanych super_; wystarczy odniesienie __class__w sposobie , jak również i to będzie działać ponownie. Komórka jest tworzona, jeśli odwołasz się do nazwy super lub __class__ w swojej metodzie:
>>> 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