2012-01-19 9 views
5

¿Cómo se puede hacer un método de clase estático después de definir la clase? En otras palabras, ¿por qué falla el tercer caso?Crear método estático a partir de un método existente fuera de la clase? (error de "método sin encuadernar")

 

>>> class b: 
... @staticmethod 
... def foo(): 
... pass 
... 
>>> b.foo() 
>>> class c: 
... def foo(): 
... pass 
... foo = staticmethod(foo) 
... 
>>> c.foo() 
>>> class d: 
... def foo(): 
... pass 
... 
>>> d.foo = staticmethod(d.foo) 
>>> d.foo() 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: unbound method foo() must be called with d instance as first argument (got nothing instead) 

Respuesta

6

Después se define la clase, foo es un objeto independiente método (un envoltorio que une la función para la clase), no una función. El contenedor tratará de pasar una instancia de la clase (self) a la función como primer argumento, por lo que se queja de que no le ha dado uno.

staticmethod() realmente debería usarse solo con funciones. Mientras la clase todavía se está definiendo (como en su b y c), foo() sigue siendo una función, ya que el envoltorio de método se aplica cuando se completa la definición de la clase.

Es posible extraer la función del objeto de método independiente, aplicar staticmethod() y asignarla nuevamente a la clase.

class d(object): 
    def foo(): 
     pass 

d.foo = staticmethod(d.foo.im_func) 

En Python 3, no hay métodos de instancia independientes (los métodos almacenados en clases son funciones simples). Por lo que su código original funcionaría realmente bien en Python 3.

Una forma en que funciona tanto en Python 2 y Python 3 es:

d.foo = staticmethod(d.__dict__['foo']) 

(También evita la creación y desechar el envoltorio método.)

+0

¿No debería ser 'd.foo.im_func'? –

+0

Sí, gracias. ¡Fijo! – kindall

+0

Bueno, necesitas marcarlos con 'método estático' para llamarlos de manera equivalente en las instancias, no solo en la clase misma. 'd.foo()' funciona con o sin envoltura 'staticmethod', pero' d(). foo() 'explotaría (intentaría pasar' self', que 'foo' no acepta). Claro, no hay ninguna función relacionada con la instancia que requiera llamarlos en una instancia, pero para DRY, los métodos que hacen referencia al método estático pueden y deben llamarlo como 'self.foo()' en lugar de nombrar explícitamente la clase. – ShadowRanger

5

Debe pasar la función, no el método independiente.

>>> class d: 
... def foo(): 
...  pass 
... 
>>> d.foo = staticmethod(d.foo.im_func) 
>>> d.foo() 
Cuestiones relacionadas