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

Python动态装饰器-为什么有这么多包装?,python,decorator,Python,Decorator,所以我对Python装饰器还是有点陌生——我以前使用过它们,但我从来没有做过自己的。我正在读(那一段),我似乎不明白为什么我们需要三个层次的功能?为什么我们不能这样做: def decorator(func, *args, **kwargs): return func(*args,**kwargs) 谢谢:)装饰程序通过向函数添加包装来修改函数。在您装饰函数时,它还没有被调用,因此您没有任何参数(或关键字参数)可查看。现在,您所能做的就是创建一个新函数,当它最终获得这些参数时,它将处理

所以我对Python装饰器还是有点陌生——我以前使用过它们,但我从来没有做过自己的。我正在读(那一段),我似乎不明白为什么我们需要三个层次的功能?为什么我们不能这样做:

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

谢谢:)

装饰程序通过向函数添加包装来修改函数。在您装饰函数时,它还没有被调用,因此您没有任何参数(或关键字参数)可查看。现在,您所能做的就是创建一个新函数,当它最终获得这些参数时,它将处理这些参数。

那么,如果您在函数上调用该装饰器,会发生什么

@decorator
def foo(): pass
这段代码会立即调用foo,这是我们不想要的。调用装饰器,其返回值替换函数。这等于说

def foo(): pass
foo = decorator(foo)
因此,如果我们有一个调用foo的decorator,我们可能希望有一个函数返回一个调用foo的函数——它返回的函数将替换foo

def decorator(f):
    def g(*args, **kwargs):
        return f(*args, **kwargs)
    return g
现在,如果我们想将选项传递给装饰器,我们不能像您的示例中那样在ide中将它们与函数并排传递。它没有语法。因此,我们定义了一个返回参数化装饰器的函数。它返回的装饰器将是一个闭包

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)

+很好的解释。最后一个“正在运行”的示例也会很有用,imho。init/call模式是另一种为装饰器提供参数的替代方法。谢谢,这真的很有帮助:)我个人不会使用decorator类,除非我想维护decorator的状态。使用闭包时,闭包是可读的。不幸的是,提问者没有:(@detly:Decorator类在应用于方法时会造成麻烦-因为它们不是函数,包装它们的对象不能被识别为方法。您必须复制instancemethod描述符的逻辑(根据Python标准,这是相对较多的样板代码,而且不明显),或者
self
不会被传入。