python - multiple - Usando super con un método de clase
metodos en python (5)
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 deberían usar un método, do_your_stuff
. (Es decir, do_something
debe 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 ). Como cls
se pasó como el segundo argumento a super()
, es cls
que se enlaza al método devuelto. En otras palabras, cls
se pasa como el primer argumento del método do_you_stuff()
.
Así que super(B, cls).do_your_stuff()
hace que se do_your_stuff
método do_your_stuff
A
con el primer argumento. Para que funcione, A
''s do_your_stuff
tiene que ser un método de clase. La página vinculada no menciona eso, pero es verdad.
PD. do_something = classmethod(do_something)
es la forma antigua de hacer un método de clase. La nueva (er) forma es usar el decorador de @classmethod.
Estoy tratando de aprender la función super () en Python.
Pensé que tenía una idea de esto hasta que encontré este ejemplo (2.6) y me encontré atascado.
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "test.py", line 9, in do_something
do_something = classmethod(do_something)
TypeError: unbound method do_something() must be called with B instance as first argument (got nothing instead)
>>>
No era lo que esperaba cuando leí esta línea justo antes del ejemplo:
Si usamos un método de clase, no tenemos una instancia para llamar a super. Afortunadamente para nosotros, Super funciona incluso con un tipo como segundo argumento. --- El tipo se puede pasar directamente a super como se muestra a continuación.
Que es exactamente lo que Python me dice que no es posible diciendo que do_something () debería llamarse con una instancia de B.
Actualicé el artículo para hacerlo un poco más claro: Atributos y métodos de Python # Super
El ejemplo que usa classmethod muestra lo que es un método de clase: pasa la clase en sí en lugar de la instancia como primer parámetro. Pero ni siquiera necesita una instancia para llamar al método, por ejemplo:
>>> class A(object):
... @classmethod
... def foo(cls):
... print cls
...
>>> A.foo() # note this is called directly on the class
<class ''__main__.A''>
Creo que ya entendí el punto gracias a este hermoso sitio y encantadora comunidad.
Si no te importa, por favor corrígeme si me equivoco en los métodos de la clase (que ahora estoy tratando de comprender completamente):
# EXAMPLE #1
>>> class A(object):
... def foo(cls):
... print cls
... foo = classmethod(foo)
...
>>> a = A()
>>> a.foo()
# THIS IS THE CLASS ITSELF (__class__)
class ''__main__.A''
# EXAMPLE #2
# SAME AS ABOVE (With new @decorator)
>>> class A(object):
... @classmethod
... def foo(cls):
... print cls
...
>>> a = A()
>>> a.foo()
class ''__main__.A''
# EXAMPLE #3
>>> class B(object):
... def foo(self):
... print self
...
>>> b = B()
>>> b.foo()
# THIS IS THE INSTANCE WITH ADDRESS (self)
__main__.B object at 0xb747a8ec
>>>
Espero que esta ilustración muestre ..
El ejemplo de la página web parece funcionar según lo publicado. ¿ do_something
un método do_something
para la superclase pero no lo convertiste en un método de clase? Algo como esto te dará ese error:
>>> class A(object):
... def do_something(cls):
... print cls
... # do_something = classmethod(do_something)
...
>>> class B(A):
... def do_something(cls):
... super(B, cls).do_something()
... do_something = classmethod(do_something)
...
>>> B().do_something()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in do_something
TypeError: unbound method do_something() must be called with B instance as first argument (got nothing instead)
En Python 3, puede omitir especificar argumentos para super
,
class A:
@classmethod
def f(cls):
return "A''s f was called."
class B(A):
@classmethod
def f(cls):
return super().f()
assert B.f() == "A''s f was called."