A veces, los textos deben leerse más por el sabor de la idea que por los detalles. Este es uno de esos casos.
En la página enlazada , los Ejemplos 2.5, 2.6 y 2.7 deben todo el método de un solo uso, do_your_stuff
. (Es decir, do_something
debería cambiarse a do_your_stuff
.)
Además, como señaló Ned Deily , A.do_your_stuff
tiene que ser un método de clase.
class A(object):
@classmethod
def do_your_stuff(cls):
print 'This is A'
class B(A):
@classmethod
def do_your_stuff(cls):
super(B, cls).do_your_stuff()
B.do_your_stuff()
super(B, cls).do_your_stuff
devuelve un método enlazado (ver nota al pie 2 ). Dado que cls
se pasó como segundo argumento a super()
, es el cls
que se vincula al método devuelto. En otras palabras, cls
se pasa como primer argumento al método do_your_stuff()
de la clase A.
Para reiterar: super(B, cls).do_your_stuff()
causas A
's do_your_stuff
método para ser llamados con cls
pasado como primer argumento. Para que eso funcione, A
's
do_your_stuff
tiene que haber un método de clase. La página vinculada no menciona eso, pero ese es definitivamente el caso.
PD. do_something = classmethod(do_something)
es la forma antigua de hacer un método de clase. La nueva (más) forma es usar el decorador @classmethod.
Tenga en cuenta que super(B, cls)
no puede ser reemplazado por super(cls, cls)
. Hacerlo podría dar lugar a bucles infinitos. Por ejemplo,
class A(object):
@classmethod
def do_your_stuff(cls):
print('This is A')
class B(A):
@classmethod
def do_your_stuff(cls):
print('This is B')
super(cls, cls).do_your_stuff()
class C(B):
@classmethod
def do_your_stuff(cls):
print('This is C')
super(cls, cls).do_your_stuff()
C.do_your_stuff()
levantará RuntimeError: maximum recursion depth exceeded while calling a Python object
.
Si cls
es así C
, super(cls, cls)
busca C.mro()
la clase que viene después C
.
In [161]: C.mro()
Out[161]: [__main__.C, __main__.B, __main__.A, object]
Dado que esa clase es B
, cuando cls
es C
, super(cls, cls).do_your_stuff()
siempre llama B.do_your_stuff
. Como super(cls, cls).do_your_stuff()
se llama por dentro B.do_your_stuff
, terminas llamando B.do_your_stuff
en un bucle infinito.
En Python3, se agregó la forma de argumento 0 de, porsuper
lo que super(B, cls)
podría reemplazarse por super()
, y Python3 averiguará a partir del contexto que super()
en la definición de class B
debería ser equivalente a super(B, cls)
.
Pero en ninguna circunstancia super(cls, cls)
(o por razones similares super(type(self), self)
) nunca es correcto.