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

Jus*_*nas 13 python decorator

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

def decorator(func, *args, **kwargs):
    return func(*args,**kwargs)
Run Code Online (Sandbox Code Playgroud)

谢谢 :)

Dev*_*rre 28

那么,如果你在一个函数上调用该装饰器会发生什么?

@decorator
def foo(): pass
Run Code Online (Sandbox Code Playgroud)

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

def foo(): pass
foo = decorator(foo)
Run Code Online (Sandbox Code Playgroud)

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

def decorator(f):
    def g(*args, **kwargs):
        return f(*args, **kwargs)
    return g
Run Code Online (Sandbox Code Playgroud)

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

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
Run Code Online (Sandbox Code Playgroud)

所以我们可以做到

decorator = argument_decorator(True)
@decorator
def foo(): pass
Run Code Online (Sandbox Code Playgroud)

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

@argument_decorator(True)
def foo(): pass
Run Code Online (Sandbox Code Playgroud)

所有这些都是非装饰器语法的语法糖

def foo(): pass
foo = argument_decorator(True)(foo)
Run Code Online (Sandbox Code Playgroud)