在装饰函数完成后,如何让 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 装饰器运行?的主要内容,如果未能解决你的问题,请参考以下文章

如何让 sphinx 识别装饰的 python 函数

如何理解Python装饰器

Python函数装饰器

Python全栈开发之8装饰器详解

Python全栈开发

python装饰器