2009-11-29 13 views
43

Estoy tratando de aprenderme la función super() en Python.Uso de super con un método de clase

Creo haberlo entendido hasta que encontré este ejemplo (2.6) y me encontré atascado.

http://www.cafepy.com/article/python_attributes_and_methods/python_attributes_and_methods.html#super-with-classmethod-example

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 de que el ejemplo:

If we're using a class method, we don't have an instance to call super with. Fortunately for us, super works even with a type as the second argument. --- The type can be passed directly to super as shown below.

¿Qué es exactamente lo que Python me dice que no es posible diciendo que hacer_algo() debe invocarse con una instancia de B.

Gracias de antemano

+0

duplicado posible de [Llamada de una clase base classmethod en Python] (https://stackoverflow.com/questions/1269217/calling-a-base-classs-classmethod-in-python) –

Respuesta

55

A veces, los textos tienen que leerse más por el sabor de la idea que por los detalles. Este es uno de esos casos. todo

En el linked page, los Ejemplos 2.5, 2.6 y 2.7 deben utilizar un método, do_your_stuff. (Es decir, do_something debería cambiarse a do_your_stuff.)

Además, como Ned Deily pointed out, A.do_your_stuff tiene que haber 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 atado método (ver footnote 2). Como se pasó el cls como el segundo argumento al 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í super(B, cls).do_your_stuff() provoca do_your_stuff método A 's para ser llamada con cls pasado como primer argumento. Para que eso funcione, A ' do_your_stuff tiene que ser un método de clase. La página vinculada no menciona eso, pero es verdad.

PS. do_something = classmethod(do_something) es la forma antigua de hacer una clase de método. La nueva forma (er) es usar el decorador @classmethod.

2

El ejemplo de la página web parece funcionar según lo publicado. ¿Creaste también un método do_something para la superclase, pero no lo convertiste en un método de clase? Algo como esto le 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) 
+0

No, mi clase A se ve así: clase A (objeto): def do_your_stuff (self): imprime "esto es A" ¿Es necesario tener "clase A" como lo publicó? (con do_something = classmethod (do_something))? Siento que el documento no dice nada sobre esto ... – dezza

+1

El objetivo de la llamada 'super' en el método B do_something es llamar a un método de ese nombre en una de sus superclases. Si no hay uno en A (o en Object), la llamada B(). Do_something() falla con 'super objeto no tiene ningún atributo do_something'. ~ unutbu correctamente señala que el ejemplo en el documento es defectuoso. –

0

Creo que he entendido el punto ahora gracias a este hermoso sitio y encantadora comunidad.

Si no te importa por favor, corríjanme si me equivoco en classmethods (que ahora estoy tratando de entender por completo):


# 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 se muestra ..

+0

Para obtener una explicación de los métodos de clase, tal vez lo encuentre útil: http://stackoverflow.com/questions/1669445/what-is-the-difference-between-a-static-method-and-class-method-in -python/1669524 # 1669524 – unutbu

2

He actualizado el artículo para que sea un poco más claro: Python Attributes and Methods # Super

Su ejemplo usando classmethod anterior muestra lo que es un método de clase es - que pasa a la propia clase en lugar de la instancia como primer parámetro. Pero usted 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'> 
1

En Python 3, puede omitir argumentos que especifican 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." 
+0

Esta respuesta podría pasar a otra pregunta si esta pregunta en particular se trata específicamente de Python 2 (es difícil de decir ya que el sitio web vinculado, CafePy, ya no está disponible). – Tankobot

Cuestiones relacionadas