2015-05-18 47 views
1

我是看的雷蒙德赫廷杰的真棒影片之一,我上了装饰例子有点糊涂:缓存装饰的Python

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 

我不是特别的装饰专家,但没有的回报调用newfunc(* args)找到该项目被缓存会导致一个永不完成的递归循环?我认为这是假设返回保存的[args](函数最终返回的结果,这是同样的事情,但我认为它永远不会到达那里,如果在缓存中找到项目)。

+0

能告诉你如何'wraps'定义? –

+0

@Asad:几乎可以肯定'从functools import wraps'。 – abarnert

+0

您可以链接到视频(最好带有时间戳) - 或者,如果他有附加的幻灯片演示文稿,请转到幻灯片?这绝对是错误的,即使Raymond Hettinger也没有超出做出愚蠢的错别字。 – abarnert

回答

2

是的,这就是一个失误。

如果你不知道,让我们来测试一下:

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页面上报告问题。

+0

罗我不希望是那个讨厌的家伙其实2年后谁指出未成年错字......只是想确保我不缺少的东西!感谢您花时间验证。 – Solaxun