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 super
zostanie 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ę super
na supper
i użyjesz, supper
ale 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 super
sł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