在装饰函数完成后,如何让 Python 装饰器运行?
Posted
技术标签:
【中文标题】在装饰函数完成后,如何让 Python 装饰器运行?【英文标题】:How can I get a Python decorator to run after the decorated function has completed? 【发布时间】:2013-01-20 03:08:09 【问题描述】:我想使用装饰器来处理各种功能的审核(主要是 Django 视图功能,但不限于此)。为了做到这一点,我希望能够审核函数 post-execution - 即函数正常运行,如果它无异常返回,那么装饰器会记录这一事实。
类似:
@audit_action(action='did something')
def do_something(*args, **kwargs):
if args[0] == 'foo':
return 'bar'
else:
return 'baz'
audit_action
只会在函数完成后运行。
【问题讨论】:
【参考方案1】:装饰器通常返回一个包装函数;只需在调用包装函数后将您的逻辑放入包装函数中即可。
def audit_action(action):
def decorator_func(func):
def wrapper_func(*args, **kwargs):
# Invoke the wrapped function first
retval = func(*args, **kwargs)
# Now do something here with retval and/or action
print('In wrapper_func, handling action !r after wrapped function returned !r'.format(action, retval))
return retval
return wrapper_func
return decorator_func
所以audit_action(action='did something')
是一个装饰器工厂,它返回一个作用域decorator_func
,用于装饰你的do_something
(do_something = decorator_func(do_something)
)。
装饰后,您的do_something
引用已替换为wrapper_func
。调用wrapper_func()
会导致调用原来的do_something()
,然后你在包装函数中的代码就可以做事了。
上面的代码,结合你的示例函数,给出以下输出:
>>> do_something('foo')
In wrapper_func, handling action 'did something' after wrapped function returned 'bar'
'bar'
【讨论】:
你不知道我用了多少种不同的装饰器、包装器、函数和 retvals 组合来尝试让它工作。不仅感谢代码,还感谢解释。 也许我遗漏了一些东西,但是你的装饰器在哪里被称为“do_something”?我期待一个@audit_action \n do_something('foo') @ColinMac:我只摸了装饰器;do_something
定义来自问题,用固定装饰器装饰。重复该示例应用程序没有什么意义。
对于正在学习的人(比如我),不清楚是否有其他事情发生。感谢您的澄清。【参考方案2】:
你的装饰器可以在这里自己处理它,比如
def audit_action(function_to_decorate):
def wrapper(*args, **kw):
# Calling your function
output = function_to_decorate(*args, **kw)
# Below this line you can do post processing
print "In Post Processing...."
return output
return wrapper
【讨论】:
OP 发布的示例使用了一个带有action
参数的装饰器工厂。您需要另一层范围界定或类..以上是关于在装饰函数完成后,如何让 Python 装饰器运行?的主要内容,如果未能解决你的问题,请参考以下文章