El nuevo super()
comportamiento mágico se agregó para evitar violar el principio SECO (No repetir), ver PEP 3135 . Tener que nombrar explícitamente la clase al hacer referencia a ella como global también es propensa a los mismos problemas de enlace que descubrió consigo super()
misma:
class Foo(Bar):
def baz(self):
return super(Foo, self).baz() + 42
Spam = Foo
Foo = something_else()
Spam().baz() # liable to blow up
Lo mismo se aplica al uso de decoradores de clases donde el decorador devuelve un nuevo objeto, que vuelve a vincular el nombre de la clase:
@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__
celda mágica evita estos problemas muy bien al darle acceso al objeto de clase original.
El PEP fue iniciado por Guido, quien inicialmente imaginó super
convertirse en una palabra clave , y la idea de usar una celda para buscar la clase actual también era suya . Ciertamente, la idea de convertirla en una palabra clave fue parte del primer borrador del PEP .
Sin embargo, fue el propio Guido quien se alejó de la idea de la palabra clave como "demasiado mágico" , proponiendo la implementación actual. Se prevé que el uso de un nombre diferente para super()
podría ser un problema :
Mi parche utiliza una solución intermedia: se supone que necesita __class__
cuando usa una variable llamada 'super'
. Por lo tanto, si (a nivel mundial) cambiar el nombre super
de supper
y el uso supper
pero no super
, no funcionará sin argumentos (pero todavía funcionará si pasarlo bien
__class__
o la clase de objeto real); si tiene una variable no relacionada llamada super
, las cosas funcionarán pero el método usará la ruta de llamada un poco más lenta utilizada para las variables de celda.
Entonces, al final, fue el propio Guido quien proclamó que usar un super
palabra clave no se sentía bien, y que proporcionar una __class__
celda mágica era un compromiso aceptable.
Estoy de acuerdo en que el comportamiento mágico e implícito de la implementación es algo sorprendente, pero super()
es una de las funciones más mal aplicadas en el lenguaje. Solo eche un vistazo a todas las invocaciones super(type(self), self)
o super(self.__class__, self)
invocaciones erróneas que se encuentran en Internet; si alguna vez se llamara a ese código desde una clase derivada , terminaría con una excepción de recursión infinita . Como mínimo, la super()
llamada simplificada , sin argumentos, evita ese problema.
En cuanto a los renombrados super_
; simplemente haga referencia __class__
en su método también y funcionará nuevamente. La celda se crea si hace referencia a los nombres super
o __class__
en su método:
>>> 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