我写了一个简单的装饰者:
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
的多次调用会返回如下输出:
foo()
> [4]
> foo called
foo()
> [4, 9]
> foo called
foo()
> [4, 9, 1]
> foo called
...
为什么?我认为decorator
只是my_dec(foo)
的语法糖?!我假设每次拨打my_dec
都会刷新lst
。
答案 0 :(得分:3)
你是对的...装饰者只是语法糖。具体做法是:
@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
和bar
时,我们会看到他们每个人都积累了自己的(不同的)随机数列表。换句话说,每次将装饰器应用于某个东西时,都会创建一个新列表,并且每次都会创建一个"某些东西"被叫,名单会增长。