【发布时间】:2011-08-11 12:25:10
【问题描述】:
所以我对 Python 装饰器还是个新手——我以前用过它们,但我从来没有自己做过。我正在阅读this tutorial(那个特定的段落),我似乎不明白为什么我们需要三个级别的函数?为什么我们不能这样做:
def decorator(func, *args, **kwargs):
return func(*args,**kwargs)
谢谢:)
【问题讨论】:
所以我对 Python 装饰器还是个新手——我以前用过它们,但我从来没有自己做过。我正在阅读this tutorial(那个特定的段落),我似乎不明白为什么我们需要三个级别的函数?为什么我们不能这样做:
def decorator(func, *args, **kwargs):
return func(*args,**kwargs)
谢谢:)
【问题讨论】:
装饰器通过添加包装器来修改函数。在你装饰函数的时候,它还没有被调用,所以你没有任何参数(或关键字参数)可以查看。你现在所能做的就是创建一个新函数,当它最终获得这些参数时将处理它们。
【讨论】:
那么,如果你在一个函数上调用那个装饰器会发生什么?
@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)
【讨论】:
self 将不会被传入。