En Python 3.x, super()
se puede invocar sin argumentos:
class A(object):
def x(self):
print("Hey now")
class B(A):
def x(self):
super().x()
>>> B().x()
Hey now
Para que esto funcione, se realiza algo de magia en tiempo de compilación, una de las cuales es que el siguiente código (que se vuelve super
a vincular super_
) falla:
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
¿Por qué super()
no se puede resolver la superclase en tiempo de ejecución sin la ayuda del compilador? ¿Existen situaciones prácticas en las que este comportamiento, o la razón subyacente del mismo, podría morder a un programador desprevenido?
... y, como una pregunta secundaria: ¿hay otros ejemplos en Python de funciones, métodos, etc. que puedan romperse volviéndolos a un nombre diferente?
python
python-3.x
super
Cero Pireo
fuente
fuente
Respuestas:
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ó consigosuper()
misma: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:
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 :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 invocacionessuper(type(self), self)
osuper(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, lasuper()
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 nombressuper
o__class__
en su método:fuente
def super(of_class=magic __class__)
especie deself.super(); def super(self): return self.__class__
?super()
sin argumentos; se trata principalmente de por qué existe.super()
, en un método de clase, es equivalente asuper(ReferenceToClassMethodIsBeingDefinedIn, self)
, dondeReferenceToClassMethodIsBeingDefinedIn
se determina en tiempo de compilación, adjunto al método como un cierre denominado__class__
, ysuper()
buscará ambos desde el marco de llamada en tiempo de ejecución. Pero en realidad no necesitas saber todo esto.super()
no está cerca de ser una función instanciada automáticamente , no.__class__
en su método . Usaste el nombresuper
en tu función. El compilador ve eso y agrega el__class__
cierre.type(self)
da el tipo actual , que no es el mismo que el tipo en el que se define el método. Entonces, una claseFoo
conbaz
necesidades de métodosuper(Foo, self).baz()
, porque podría subclasificarse comoclass Ham(Foo):
, en ese puntotype(self)
esHam
ysuper(type(self), self).baz()
le daría un bucle infinito. Vea la publicación a la que enlazo en mi respuesta: Al llamar a super () en una clase derivada, ¿puedo pasar en sí.