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 super
diventare 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 super
per supper
e uso supper
ma 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 super
parola 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