Dlaczego Python 3.X ' s super() magic?
W Pythonie 3.x, super()
można wywołać bez argumentów:
class A(object):
def x(self):
print("Hey now")
class B(A):
def x(self):
super().x()
>>> B().x()
Hey now
Aby to zadziałało, wykonywana jest magia czasu kompilacji, której konsekwencją jest to, że następujący kod (który zmienia super
na super_
) nie działa:
super_ = super
class A(object):
def x(self):
print("No flipping")
class B(A):
def x(self):
super_().x()
>>> B().x()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in x
RuntimeError: super(): __class__ cell not found
Dlaczego super()
nie jest w stanie rozwiązać superklasy w czasie wykonywania bez pomocy kompilatora? Czy istnieją praktyczne sytuacje, w których takie zachowanie lub jego przyczyna mogłyby ugryźć nieostrożny programista?
... i pytanie poboczne: czy w Pythonie są jakieś inne przykłady funkcji, metod itp. które można złamać zmieniając je na inne imię?
1 answers
Dodano nowe zachowanie magiczne super()
, aby uniknąć naruszenia zasady D. R. Y. (nie powtarzaj się), zobacz PEP 3135 . W przeciwieństwie do innych klas, klasy te mogą być używane jako klasy globalne, ale nie mogą być używane jako klasy globalne.]}
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życia dekoratorów klasy, gdzie dekorator zwraca nowy obiekt, który ponownie zmienia 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
Magia super()
__class__
cell ładnie pomija te problemy przez daje Ci dostęp do oryginalnego obiektu klasy.
PEP został uruchomiony przez Guido, który początkowo zakładał, że super
stanie się słowem kluczowym , a pomysł użycia komórki do znalezienia bieżącej klasy był również jego. Oczywiście, pomysł, aby to słowo kluczowe było częścią pierwszy szkic PEP.
super()
może być problemem :
Ostatecznie to sam Guido stwierdził, że użycie słowa kluczowego nie jest w porządku, a dostarczenie magicznej komórki jest akceptowalnym kompromisem.Mój patch używa rozwiązania pośredniego: zakłada, że potrzebujesz
__class__
ilekroć używasz zmiennej o nazwie'super'
. Tak więc, jeśli (globalnie) Zmień nazwęsuper
nasupper
i użyjsupper
, ale niesuper
, to nie zadziała bez argumentów (ale i tak będzie działać, jeśli go przekażesz albo__class__
lub rzeczywisty obiekt klasy); jeśli masz niepowiązany zmienna o nazwiesuper
, wszystko będzie działać, ale metoda wykorzysta nieco wolniejsza ścieżka wywołania używana dla zmiennych komórki.
Zgadzam się, że magiczne, Ukryte zachowanie implementacji jest nieco zaskakujące, ale super()
jest jedną z najbardziej błędnych funkcji w języku. Wystarczy spojrzeć na wszystkie źle stosowane super(type(self), self)
lub super(self.__class__, self)
wywołania Znalezione w Internecie; gdyby któryś z tych kodów został wywołany z pochodnej klasy , skończyłbyś z nieskończonym wyjątkiem rekurencyjnym. Przynajmniej uproszczone wywołanie super()
, bez argumentów, unika tego problemu.
Jeśli chodzi o nazwę super_
; wystarczy odwołać się __class__
w swojej metodzie , jak również i będzie działać ponownie. Komórka jest tworzona, jeśli odwołujesz się do super
lub __class__
imiona w Twoim "metoda": {]}
>>> 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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-10 18:27:45