Python动态装饰器 - 为什么这么多包裹?

时间:2011-04-23 15:01:26

标签: python decorator

所以我对Python装饰者还是个新手 - 我以前用过它们,但我从来没有自己做过。我正在阅读this tutorial(特定段落),我似乎不明白为什么我们需要三个级别的功能?为什么我们不能这样做:

def decorator(func, *args, **kwargs):
    return func(*args,**kwargs)

谢谢:)

2 个答案:

答案 0 :(得分:27)

那么,如果你在一个函数上调用那个装饰器会怎么样?

@decorator
def foo(): pass

这段代码会立即调用foo,这是我们不想要的。调用装饰器并且它们的返回值替换该函数。这和说

一样
def foo(): pass
foo = decorator(foo)

因此,如果我们有一个调用foo的装饰器,我们可能希望有一个函数返回一个调用foo的函数 - 它返回的函数将替换foo。

def decorator(f):
    def g(*args, **kwargs):
        return f(*args, **kwargs)
    return g

现在,如果我们想要将选项传递给装饰器,我们就不能像在你的例子中一样将它们完全传递给函数。它没有语法。所以我们定义一个返回参数化装饰器的函数。它返回的装饰器将是一个闭包。

def argument_decorator(will_I_call_f):
    def decorator(f):
        def g(*args, **kwargs):
            if will_I_call_f: return f(*args, **kwargs)
        return g
    return decorator

所以我们可以做到

decorator = argument_decorator(True)
@decorator
def foo(): pass

Python提供了内联函数调用的便捷语法:

@argument_decorator(True)
def foo(): pass

所有这些都是

的非装饰器语法的语法糖
def foo(): pass
foo = argument_decorator(True)(foo)

答案 1 :(得分:3)

装饰器通过向其添加包装来修改函数。在装饰函数时,它尚未被调用,因此您没有任何参数(或关键字参数)可供查看。你现在所能做的只是创建一个新函数,它将在最终得到它们时处理这些参数。