2010-01-01 12 views
25

¿Por qué decorator no decora un método estático o un método de clase?¿Por qué @decorator no puede decorar un método estático o un método de clase?

from decorator import decorator 

@decorator 
def print_function_name(function, *args): 
    print '%s was called.' % function.func_name 
    return function(*args) 

class My_class(object): 
    @print_function_name 
    @classmethod 
    def get_dir(cls): 
     return dir(cls) 

    @print_function_name 
    @staticmethod 
    def get_a(): 
     return 'a' 

Tanto get_dir y get_a resultado en AttributeError: <'classmethod' or 'staticmethod'>, object has no attribute '__name__'.

¿Por qué se basa decorator en el atributo __name__ en lugar del atributo func_name? (Todas las funciones de Afaik, incluidos classmethods y staticmethods, tienen el atributo func_name).

Editar: Estoy usando Python 2.6.

+1

función ¿Por qué llamas (* args) dentro del decorador? Su función es simplemente devolver una función (en su caso, no modificada). – gahooa

+4

gahooa: porque es una forma de 'decorador' (lo que importa, no la construcción del lenguaje) funciona, ver http://pypi.python.org/pypi/decorator. –

+0

@taldor tiene un módulo de decorador en py 2.6? – mykhal

Respuesta

22

funciona cuando @classmathod y @staticmethod son los más superiores decoradores:

from decorator import decorator 

@decorator 
def print_function_name(function, *args): 
    print '%s was called.' % function.func_name 
    return function(*args) 

class My_class(object): 
    @classmethod 
    @print_function_name 
    def get_dir(cls): 
     return dir(cls) 
    @staticmethod 
    @print_function_name 
    def get_a(): 
     return 'a' 
+7

Como regla, 'classmethod' y 'staticmethod' aplica un tipo especial de magia y debe llamarse último. –

3

¿Esto es lo que quería?

def print_function_name(function): 
    def wrapper(*args): 
     print('%s was called.' % function.__name__) 
     return function(*args) 
    return wrapper 

class My_class(object): 
    @classmethod 
    @print_function_name 
    def get_dir(cls): 
     return dir(cls) 

    @staticmethod 
    @print_function_name 
    def get_a(): 
     return 'a' 
+2

No estoy seguro de que te hayas dado cuenta, pero el paquete de "decorador" que está usando hace lo mismo que la construcción con "envoltura". La única diferencia entre los fragmentos es el orden de aplicación de los decoradores en My_class. Puede aclarar eso en la respuesta para explicar por qué soluciona las cosas. –

+0

Gracias por una corrección. Estaba jugando con el problema en py3k, donde falta el módulo decorador. Quería decir que mi respuesta era la más rápida, y estaba seguro de que alguien publicaría la mejor respuesta con la explicación detallada – mykhal

+0

@ (Peter Hansen) ... sin embargo, no hay un módulo decorador en Python 2.6 tampoco – mykhal

37

classmethod y staticmethod retorno descriptor objects, no funciones. La mayoría de los decoradores no están diseñados para aceptar descriptores.

Normalmente, entonces debe aplicar classmethod y staticmethod al usar decoradores múltiples. Y dado que los decoradores se aplican en orden ascendente, classmethod y staticmethod normalmente deben ser de primer nivel en su fuente.

De esta manera:

class My_class(object): 
    @classmethod 
    @print_function_name 
    def get_dir(cls): 
     return dir(cls) 

    @staticmethod 
    @print_function_name 
    def get_a(): 
     return 'a' 
+7

+1 por responder la pregunta ("¿por qué ...?"). –

Cuestiones relacionadas