Почему @decorator не может украсить staticmethod или classmethod?
Почему decorator
не может украсить статический метод или метод класса?
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'
И get_dir
и get_a
приводят к AttributeError: <'classmethod' or 'staticmethod'>, object has no attribute '__name__'
.
Почему decorator
полагается на атрибут __name__
вместо атрибута func_name
? (Во всех функциях, включая методы классов и статические методы, есть атрибут func_name
.)
Редактировать: я использую Python 2.6.
Ответы
Ответ 1
Это работает, когда @classmethod
и @staticmethod
- самые лучшие декораторы:
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'
Ответ 2
classmethod
и staticmethod
возвращают объекты дескриптора, а не функции. Большинство декораторов не предназначены для приема дескрипторов.
Как правило, тогда вы должны применять classmethod
и staticmethod
последними при использовании нескольких декораторов. А поскольку декораторы применяются в порядке "снизу вверх", classmethod
и staticmethod
обычно должен быть самым верхним в вашем источнике.
Как это:
class My_class(object):
@classmethod
@print_function_name
def get_dir(cls):
return dir(cls)
@staticmethod
@print_function_name
def get_a():
return 'a'
Ответ 3
Это то, что вы хотели?
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'