Il nuovo super()comportamento magico è stato aggiunto per evitare di violare il principio DRY (Don't Repeat Yourself), vedi PEP 3135 . Dover nominare esplicitamente la classe facendo riferimento a essa come globale è anche soggetto agli stessi problemi di rebinding che hai scoperto con super()se 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 l'utilizzo di decoratori di classi in cui il decoratore restituisce un nuovo oggetto, che ribattezza 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 super() __class__cellula magica elimina bene questi problemi dandoti l'accesso all'oggetto classe originale.
Il PEP è stato lanciato da Guido, che inizialmente aveva previsto di superdiventare una parola chiave , e l'idea di usare una cella per cercare la classe attuale era anche sua . Certamente, l'idea di farne una parola chiave faceva parte della prima bozza del PEP .
Tuttavia, è stato in effetti lo stesso Guido a rinunciare all'idea della parola chiave come "troppo magico" , proponendo invece l'attuale implementazione. Ha anticipato che l'uso di un nome diverso per super()potrebbe essere un problema :
La mia patch usa una soluzione intermedia: presume che tu abbia bisogno __class__
ogni volta che usi una variabile chiamata 'super'. Pertanto, se (globalmente) rinomina superper suppere uso supperma non super, non funzionerà senza argomenti (ma continuerà a funzionare se si passa sia
__class__o all'oggetto classe reale); se hai una variabile non correlata chiamata super, le cose funzioneranno ma il metodo utilizzerà il percorso di chiamata leggermente più lento usato per le variabili di cella.
Quindi, alla fine, fu lo stesso Guido a proclamare che l'uso di una superparola chiave non sembrava corretto e che fornire una __class__cellula magica era un compromesso accettabile.
Concordo sul fatto che il comportamento magico e implicito dell'implementazione sia in qualche modo sorprendente, ma super()sia una delle funzioni più erroneamente applicate nel linguaggio. Dai un'occhiata a tutte le applicazioni errate super(type(self), self)o super(self.__class__, self) invocate trovate su Internet; se qualcuno di quel codice fosse mai stato chiamato da una classe derivata si finirebbe con un'eccezione di ricorsione infinita . Per lo meno la super()chiamata semplificata , senza argomenti, evita quel problema.
Per quanto riguarda il rinominato super_; appena riferimento __class__nel metodo così e che funzionerà di nuovo. La cella viene creata se si fa riferimento ai nomi super o __class__ 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