缓存装饰器 Python
Caching Decorator Python
我正在观看 Raymond Hettinger 的一个很棒的视频,我对装饰器示例有点困惑:
def cache(func):
saved={}
@wraps(func)
def newfunc(*args):
if args in saved:
return newfunc(*args) # should be return saved[args]?
result = func(*args)
saved[args]=result
return result
return newfunc
我不是装饰器方面的专家,但是 return 在发现项目被缓存后调用 newfunc(*args) 不会导致递归循环永远不会结束吗?我认为它是假设 return 保存 [args] (函数最终 return 的结果,这是一回事,但我认为如果在中找到一个项目它永远不会到达那里缓存。)
是的,这是一个错误。
如果您不确定,让我们测试一下:
def fib(n):
if n < 2:
return 1
return fib(n-2) + fib(n-1)
print(fib(10))
@cache
def cfib(n):
if n < 2:
return 1
return cfib(n-2) + cfib(n-1)
print(cfib(10))
第一个打印出89
,第二个中止:
File "rhcache.py", line 8, in newfunc
return newfunc(*args) # should be return saved[args]?
File "rhcache.py", line 8, in newfunc
return newfunc(*args) # should be return saved[args]?
# ... 997 more copies
RuntimeError: maximum recursion depth exceeded
但是如果我们按照您的建议更改它,它会再次打印 89
。 (而且,如果你计时,它比非缓存版本运行得更快;如果你分析它,它只对实际函数进行 10 次调用;等等)
完全符合您的预期。
那么,我们学到了什么?即使是 Raymond Hettinger 也不会在未经测试的代码中偶尔出现拼写错误,但他的代码足够干净,即使没有 运行 也很容易找到并解决问题。 :)
您可以向他发送电子邮件、在 YouTube 页面上添加评论或在 PyVideo 页面上报告问题。
您也可以使用 @functools.lru_cache(maxsize=128, typed=False)¶
这看起来像:
from functools import lru_cache
@lru_cache(maxsize=None)
def fib(n):
if n < 2:
return n
return fib(n-1) + fib(n-2)
我正在观看 Raymond Hettinger 的一个很棒的视频,我对装饰器示例有点困惑:
def cache(func):
saved={}
@wraps(func)
def newfunc(*args):
if args in saved:
return newfunc(*args) # should be return saved[args]?
result = func(*args)
saved[args]=result
return result
return newfunc
我不是装饰器方面的专家,但是 return 在发现项目被缓存后调用 newfunc(*args) 不会导致递归循环永远不会结束吗?我认为它是假设 return 保存 [args] (函数最终 return 的结果,这是一回事,但我认为如果在中找到一个项目它永远不会到达那里缓存。)
是的,这是一个错误。
如果您不确定,让我们测试一下:
def fib(n):
if n < 2:
return 1
return fib(n-2) + fib(n-1)
print(fib(10))
@cache
def cfib(n):
if n < 2:
return 1
return cfib(n-2) + cfib(n-1)
print(cfib(10))
第一个打印出89
,第二个中止:
File "rhcache.py", line 8, in newfunc
return newfunc(*args) # should be return saved[args]?
File "rhcache.py", line 8, in newfunc
return newfunc(*args) # should be return saved[args]?
# ... 997 more copies
RuntimeError: maximum recursion depth exceeded
但是如果我们按照您的建议更改它,它会再次打印 89
。 (而且,如果你计时,它比非缓存版本运行得更快;如果你分析它,它只对实际函数进行 10 次调用;等等)
完全符合您的预期。
那么,我们学到了什么?即使是 Raymond Hettinger 也不会在未经测试的代码中偶尔出现拼写错误,但他的代码足够干净,即使没有 运行 也很容易找到并解决问题。 :)
您可以向他发送电子邮件、在 YouTube 页面上添加评论或在 PyVideo 页面上报告问题。
您也可以使用 @functools.lru_cache(maxsize=128, typed=False)¶ 这看起来像:
from functools import lru_cache
@lru_cache(maxsize=None)
def fib(n):
if n < 2:
return n
return fib(n-1) + fib(n-2)