我一直在研究如何创建自己的装饰器,并给出了以下示例:
def counter(func):
def wrapper(*args, **kwargs):
wrapper.count += 1
# Call the function being decorated and return the result
return wrapper.count
wrapper.count = 0
# Return the new decorated function
return wrapper
# Decorate foo() with the counter() decorator
@counter
def foo():
print('calling foo()')
foo()
foo()
print('foo() was called {} times.'.format(foo.count))
我不明白那段代码的逻辑。wrapper.count
)? 最佳答案
- How can I reference a function inside itself (wrapper.count)?
函数体只有在你调用它时才会执行。到那时,该功能已经定义,所以这就是使之成为可能的原因。以下不会给您任何错误,除非您调用它:
>>> def foo():
... non_existing_function()
...
每当你进入 foo
的正文, foo
已经定义好了,所以你可以引用它。这也是使递归调用成为可能的原因。
- How wrapper has the method count before wrapper is defined?
问题也可能是“如何在
wrapper.count
初始化之前增加它?”但同样,我们可以用同样的方式回答这个问题:因为函数体在我们调用它们之前不会被执行,
wrapper.count
在 wrapper.count += 1
之前初始化为 0 .
- Shouldn't the line wrapper.count = 0 be executed everytime I call foo()?
让我们看看发生了什么。你写:
@counter
def foo():
print('calling foo()')
这只是一个语法糖:foo = counter(foo)
现在,我们调用counter
功能与 foo
作为论据。什么counter
做?def counter(func):
def wrapper(*args, **kwargs):
wrapper.count += 1
# Call the function being decorated and return the result
return wrapper.count
wrapper.count = 0
# Return the new decorated function
return wrapper
在人类语言中,wrapper
的函数它采用未知数量的位置和关键字参数 0
作为一个名为 count
的属性对于 wrapper
功能 wrapper
给来电者当我们将结果分配回
foo
函数,我们实际上分配了wrapper
至foo
.所以当我们调用 foo
,我们实际上是在调用 wrapper
.行wrapper.count = 0
在 wrapper
之外函数,所以它不会在我们每次调用 foo
时运行.最后,我强烈建议您观看精彩PyCon talk by Reuven M. Lerner关于装饰师。
编辑:我没有阅读包装器的正文,这实际上证明您并不需要知道包装器内的内容。我的解释仍然是正确的。但是,正如 @Mark Tolonen's answer 中所建议的那样,您的包装器可能应该返回
func(*args,**kwargs)
不是 wrapper.count
关于python-3.x - 了解这个 Python 装饰器是如何工作的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62576512/