例如:
def decorator(func):
def nested(*args, **kwargs):
return func(*args, **kwargs)
return nested
@decorator
def decorated(): pass
有没有办法让装饰者知道它正在被装饰?
答案 0 :(得分:1)
以下是一个部分解决方案,适用于与您的示例完全相似的闭包。
import inspect
def decorator(func):
def nested(*args, **kwargs):
return func(*args, **kwargs)
return nested
@decorator
def decorated(): pass
def not_decorated(): pass
print(inspect.getclosurevars(decorated).nonlocals)
print(inspect.getclosurevars(not_decorated).nonlocals)
# => {'func': <function decorated at 0x10e1408c8>}
# => {}
像您这样的装饰函数将具有闭包变量,尽管不能保证其他函数不会。
此外,inspect
中还有其他可以玩的东西。另外,如果首先使用functools.wrap
(@kindall),将很容易。对于类方法,您可以查询How to detect is decorator has been applied to method or function?
答案 1 :(得分:1)
您可以使用装饰器,该装饰器使用ast.NodeVistor
遍历函数的AST节点以查找函数的装饰器。如果装饰器列表包含的内容不止装饰器检查器本身,则可以从装饰器节点获取其他装饰器的详细信息:
import inspect
import ast
from textwrap import dedent
class CheckDecorators(ast.NodeVisitor):
def visit_FunctionDef(self, node):
if len(node.decorator_list) > 1:
print("function '%s' is decorated by: %s" % (node.name, ', '.join(ast.dump(decorator) for decorator in node.decorator_list if not isinstance(decorator, ast.Name) or decorator.id != 'check_decorators')))
def check_decorators(func):
CheckDecorators().visit(ast.parse(dedent(inspect.getsource(func))))
return func
这样:
def decorator(func):
def nested(*args, **kwargs):
return func(*args, **kwargs)
return nested
@decorator
@check_decorators
def decorated():
pass
将输出:
function 'decorated' is decorated by: Name(id='decorator', ctx=Load())