Я пытаюсь выяснить, как получить имена всех декораторов на методе. Я могу уже получить имя метода и docstring, но не могу выяснить, как получить список декораторов.
Если вы можете изменить способ вызова декораторов с
class Foo(object):
@many
@decorators
@here
def bar(self):
pass
на
class Foo(object):
@register(many,decos,here)
def bar(self):
pass
то вы можете зарегистрировать декораторы таким образом:
def register(*decorators):
def register_wrapper(func):
for deco in decorators[::-1]:
func=deco(func)
func._decorators=decorators
return func
return register_wrapper
Например:
def many(f):
def wrapper(*args,**kwds):
return f(*args,**kwds)
return wrapper
decos = here = many
class Foo(object):
@register(many,decos,here)
def bar(self):
pass
foo=Foo()
Здесь мы обращаемся к кортежу декораторов:
print(foo.bar._decorators)
# (<function many at 0xb76d9d14>, <function decos at 0xb76d9d4c>, <function here at 0xb76d9d84>)
Здесь мы печатаем только имена декораторов:
print([d.func_name for d in foo.bar._decorators])
# ['many', 'decos', 'here']
Это потому, что декораторы - это «синтаксический сахар». Допустим, у вас есть следующий декоратор:
def MyDecorator(func):
def transformed(*args):
print "Calling func " + func.__name__
func()
return transformed
И вы применяете его к функции:
@MyDecorator
def thisFunction():
print "Hello!"
Это эквивалентно:
thisFunction = MyDecorator(thisFunction)
Вы можете встроить «историю» в объект функции, возможно, если вы контролируете декораторы. Бьюсь об заклад, есть другой умный способ сделать это (возможно, переопределив присвоение), но, к сожалению, я не так хорошо разбираюсь в Python. : (
Нельзя, но еще хуже то, что существуют библиотеки, помогающие скрыть тот факт, что вы декорировали функцию для начала. Смотрите Functools или библиотеку decorator (@decorator
, если я смог ее найти) для получения дополнительной информации.
Это невозможно сделать обычным способом, потому что
@foo
def bar ...
в точности совпадает с
def bar ...
bar = foo (bar)
. Вы можете сделать это в некоторых особых случаях, например, вероятно, @staticmethod
, анализируя объекты функций, но не лучше, чем это.
Как Фейсал отмечает , декораторы могут сами прикреплять метаданные к функции, но, насколько мне известно, это не делается автоматически.
That's not possible in my opinion. Декоратор - это не какой-то атрибут или метаданные метода. Декоратор - это удобный синтаксис для замены функции результатом вызова функции. Подробнее см. в http://docs.python.org/whatsnew/2.4.html?highlight=decorators#pep-318-decorators-for-functions-and-methods.