首先,我知道装饰者是什么。我想了解一些小方面。
TL; DR
is decorator func1 = func2(func1) # True
is decorator func3 = func2(func1) # ???
让我们看一下Wiki,它描述了两种等效的装饰函数的方法:
@viking_chorus
def menu_item():
print("spam")
def menu_item():
print("spam")
menu_item = viking_chorus(menu_item)
现在,让我们看一下这个website的描述,特别是回到装饰者部分。定义了两个函数:
def make_pretty(func):
def inner():
print("I got decorated")
func()
return inner
def ordinary():
print("I am ordinary")
然后作者装饰该函数并调用它:
>>> pretty = make_pretty(ordinary)
>>> pretty()
I got decorated
I am ordinary
我们可以注意到作者没有使用:
>>> ordinary = make_pretty(ordinary)
这是Wiki推荐的方式(我知道Wiki有时可能是错误的)。所以我决定使用最后一种方法来装饰从tutorial取得的Fibonacci数字函数:
def memoize(f):
memo = {}
def helper(x):
if x not in memo:
memo[x] = f(x)
return memo[x]
return helper
def fib(n):
if n == 0:
return 0
elif n == 1:
return 1
else:
return fib(n-1) + fib(n-2)
这个电话:
>>> fib_element = memoize(fib)
>>> fib_element(40)
在我的机器上花费很长时间,这意味着fib()
未正确装饰。执行时间与fib(40)
相当。这些电话:
>>> fib = memoize(fib)
>>> fib_element = fib # assigned after decoration
>>> fib(40)
>>> fib_element(40)
快速执行。所以问题是:我们可以说我们在ordinary
作业中装饰了pretty = make_pretty(ordinary)
函数吗?
答案 0 :(得分:2)
第一次调用fib_element(40)
的原因是你没有递归装饰:fib
函数不知道你的memoization。如果你在同一个元素上反复调用fib_element
,第一个调用会很慢,其他调用会非常快。
由于fib
调用fib
(它引用第二个示例中的修饰函数,但是第一个示例中的原始函数),因此需要为其提供相同的名称以便从memoization中获益这种装饰方法。