我在 python 中搞乱了记忆,并使用了一个示例斐波那契序列函数作为模型。我将第一个
fibonacci()
函数编写为常规函数,无需记忆,它按预期工作。接下来,我编写了我的
fibonacci_memo()
函数,该函数使用带有输出的输入字典来利用记忆化,并且按预期工作。然后我想测试 functools 缓存装饰器,看看它是否达到了我预期的相同效果。因此,我复制了不使用记忆化的初始
fibonacci()
函数,并在其上添加了 @cache 装饰器。然而,结果是出乎意料的,因为它似乎与不使用记忆化的原始
fibonacci()
函数运行相同。
我是否对装饰器的实用性或一般记忆化有误解?代码如下,感谢任何帮助!
from functools import cache
def fibonacci(n):
if n == 0:
return 0
elif n == 1:
return 1
return fibonacci(n - 1) + fibonacci(n - 2)
print(fibonacci(23))
# instant, works as expected
def fibonacci_memo(n, memo:dict={}):
if n == 0:
return 0
elif n == 1:
return 1
if n in memo:
return memo[n]
memo[n] = fibonacci_memo(n - 1, memo) + fibonacci_memo(n - 2, memo)
return fibonacci_memo(n - 1, memo) + fibonacci_memo(n - 2, memo)
print(fibonacci_memo(500))
# instant, works as expected
@cache
def fibonacci_functools(n): # identical to first, basic fibonacci function
if n == 0:
return 0
elif n == 1:
return 1
return fibonacci(n - 1) + fibonacci(n - 2)
print(fibonacci_functools(500))
# slow, shouldn't it be te same as fibonacci_memo()??
问题出在你的
fibonacci_functools
函数中,你调用的是
原始的
fibonacci
函数
,而不是调用自身递归。这意味着它没有利用
@cache
装饰器提供的记忆化功能。
以下是如何修复它的方法:
from functools import cache
@cache
def fibonacci_functools(n):
if n == 0:
return 0
elif n == 1:
return 1
return fibonacci_functools(n - 1) + fibonacci_functools(n - 2) # 调用自身
print(fibonacci_functools(500)) # 现在应该很快了
通过在递归步骤中调用
fibonacci_functools
,装饰器可以缓存每个结果,从而产生与
fibonacci_memo
函数相同的性能提升。