Il nuovo comportamento magico super()
è stato aggiunto per evitare la violazione del D.R.Y. (Non ripetere te stesso) principio, vedi PEP 3135. Dovendo nominare esplicitamente la classe facendo riferimento a come globale è anche soggetta agli stessi problemi di rebinding si scoprì con super()
stesso:
class Foo(Bar):
def baz(self):
return super(Foo, self).baz() + 42
Spam = Foo
Foo = something_else()
Spam().baz() # liable to blow up
Lo stesso vale per utilizzando decoratori di classe dove il decoratore restituisce un nuovo oggetto, che rebinds il nome della classe:
@class_decorator_returning_new_class
class Foo(Bar):
def baz(self):
# Now `Foo` is a *different class*
return super(Foo, self).baz() + 42
la magia delle cellule super()
__class__
evita questi problemi piacevolmente dando accesso all'oggetto classe originale.
Il PEP è stato avviato da Guido, che è initially envisioned super
becoming a keyword, e l'idea di utilizzare una cella per cercare la classe corrente was also his. Certamente, l'idea di farne una parola chiave faceva parte dello first draft of the PEP.
Tuttavia, era in realtà Guido stesso che quindi stepped away from the keyword idea as 'too magical', proponendo invece l'implementazione corrente. Egli anticipated that using a different name for super()
could be a problem:
mia patch utilizza una soluzione intermedia: assume il necessario __class__
ogni volta che si utilizza una variabile denominata 'super'
. Pertanto, se (globalmente) rinomina super
a supper
e utilizzare supper
ma non super
ma non funzionerà senza argomenti (ma continuerà a funzionare se si passa neanche __class__
o l'oggetto classe reale); se si dispone di una variabile non correlata denominata super
, le cose funzioneranno ma il metodo utilizzerà il percorso di chiamata leggermente più lento utilizzato per le variabili di cella.
Così, alla fine, è stato Guido se stesso che ha proclamato che utilizzando una parola chiave super
non si sentiva bene, e che fornire una magia delle cellule __class__
era un compromesso accettabile.
Sono d'accordo sul fatto che la magia, il comportamento implicito dell'implementazione è in qualche modo sorprendente, ma super()
è una delle funzioni più male applicate nella lingua. Basta dare un'occhiata a tutte le chiamate errate super(type(self), self)
o super(self.__class__, self)
trovate su Internet; se qualcuno di quel codice è stato mai chiamato da una classe derivata you'd end up with an infinite recursion exception. Per lo meno la chiamata semplificata super()
, senza argomenti, evita lo del problema.
Come per il nome super_
; basta fare riferimento a __class__
nel metodo e e funzionerà di nuovo. La cella si crea se si fa riferimento sia alle super
o__class__
nomi nel metodo:
>>> 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
vi svelo Armin fare lo spiega in questo [uno] (http://lucumr.pocoo.org/2010/1/7/pro-e-contro-about-python-3 /). Anche questo è un altro buon [post] (http://lucumr.pocoo.org/2013/5/21/porting-to-python-3-redux/) –
correlato: http://stackoverflow.com/q/36993577/674039 – wim