2011-03-17 10 views
5

Tengo un pequeño problema al decorar un método estático en Python. Creo que el siguiente código representa mejor mi problema:Python: Método estático decorado que recibe el método no desechable

def decorator(func): 
    print callable(func) 
    return func 

class Foo(): 
    @decorator 
    @staticmethod 
    def bar(): 
     return 

# outputs False 

print callable(Foo.bar) 
# outputs True 

Esto parece ser un error. Me imagino que surge porque cuando el método Foo.bar se pasa al decorador, es una función, no un método. Esa es la única razón por la que veo que no se puede llamar, ya que si decoramos una función estándar, no se puede llamar, como se muestra a continuación.

@staticmethod 
def function(): 
    return 

print callable(function) 
# outputs False 

Así es esto un cierto error en la aplicación del decorador métodoestático, y/o existen soluciones provisionales simples? Pensé en escribir un decorador para asignar un atributo __call__, pero no sé cómo se implementa callable, por lo que no puedo medir el éxito de dicho método.

+0

Tenga en cuenta que debe usar las clases de estilo nuevo para que un 'método estático' sea invocado también en instancias, ya que esto usa descriptores. –

+2

Para que funcione, simplemente cambie el orden de los descriptores. –

Respuesta

4

Métodos son funciones. Pero los objetos staticmethod no lo son. Son descriptors, por lo que hay magia extra que te permite llamar cuando accedes a ella como Cls.static_method, pero esta magia no puede ocultar nada cuando usas (es decir, pasas al decorador) static_method dentro del cuerpo de Cls. Realmente no puedes hackear esto, al menos no limpiamente. Una solución mucho más simple es reordenar los decoradores de modo que staticmethod se apliquen por última vez, es decir, ponerlo en la parte superior, por encima de todos los demás decoradores.

+0

Ah, eso tiene sentido. Gracias. –

4

Pues bien, si se tiene en cuenta que un error o no, es documented:

objetos método estático proporcionan una manera de derrotar a la transformación de objetos de función al método de objetos descrito anteriormente. Un objeto de método estático es un contenedor alrededor de cualquier otro objeto , generalmente un objeto de método definido por el usuario. Cuando un objeto de método estático es recuperado de una instancia de clase o clase , el objeto realmente devuelto es el objeto envuelto, que no está sujeto a cualquier transformación posterior. Los objetos del método estático no son mismos que se pueden llamar, aunque los objetos que envuelven suelen ser. Los objetos de método Static se crean mediante el constructor de método estático incorporado .

0

Escribí mi propia implementación de staticmethod que es invocable y esto parece resolver este problema muy bien.

class staticmethod(object): 
    """Make @staticmethods play nice with @memoize.""" 

    def __init__(self, func): 
     self.func = func 

    def __call__(self, *args, **kwargs): 
     """Call the static method with no instance.""" 
     return self.func(*args, **kwargs) 

Este no utiliza el protocolo descriptor y como tal se comporta muy diferente a la orden interna staticmethod internamente, sin embargo, en la práctica, se hace que las funciones se puede llamar como atributos de la clase, los atributos de ejemplo, e incluso como atributos de función (es decir, si ha envuelto su clase en una función de decoración, esta implementación de método estático le permitirá llamar a sus métodos estáticos como atributos en la función de envoltura).

Cuestiones relacionadas