我写了一个简单的装饰器:
from functools import wraps
import random
def my_dec(f):
lst = list()
@wraps(f)
def wrapper(*args):
lst.append(random.randint(0, 9))
print(lst)
return f(*args)
return wrapper
@my_dec
def foo():
print("foo called")
现在,如果我foo
多次拨打电话,lst
则不会被刷新。相反,它会随着时间的推移而累积。因此,多次调用foo
return将返回如下输出:
foo()
> [4]
> foo called
foo()
> [4, 9]
> foo called
foo()
> [4, 9, 1]
> foo called
...
这是为什么?我以为decorator
是语法糖my_dec(foo)
吗?!我以为每次对my_dec
flush的调用lst
。
您说得对...装饰器只是语法糖。具体来说:
@decorator
def foo():
pass
与以下内容完全相同:
def foo():
pass
foo = decorator(foo)
让我们多了几分古怪和重写这个法子是大多相当于1:
def bar():
pass
foo = decorator(bar)
del bar
希望以这种方式写出来,您可以看到,如果我打电话foo
很多次,我就不会打电话decorator
很多次。decorator
仅被调用一次(以帮助创建foo
)。
现在在您的示例中,装饰器在被调用时立即创建一个列表:
def my_dec(f):
lst = list() # list created here!
@wraps(f)
def wrapper(*args):
lst.append(random.randint(0, 9))
print(lst)
return f(*args)
return wrapper
返回的函数wrapper
将分配给您foo
,因此调用时即foo
在调用wrapper
。请注意,没有代码wrapper
可以重置lst
-仅代码会添加更多元素,lst
因此这里没有任何内容表明调用之间lst
应该“清除”。
1(取决于装饰器的功能,您可能会在函数的__name__
属性中看到一些差异,但否则是同一回事...)
还要注意,lst
每次调用装饰器时,您都会得到一个。如果我们喜欢并装饰foo
两次,我们可以为之疯狂:
@my_dec
@my_dec
def foo():
pass
或者,我们可以装饰多个功能:
@my_dec
def foo():
pass
@my_dec
def bar():
pass
然后,当我们调用foo
and时bar
,我们将看到它们各自积累了自己的(不同的)随机数列表。换句话说,每次将装饰器应用于某物时,都会创建一个新列表,并且每次调用“某物”时,该列表都会增长。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句