Python 不会延迟计算参数。
传递给dict.get调用的默认值也将在调用dict.get之前进行评估。
因此,在您的情况下,默认值具有递归调用,并且由于您的条件从未满足,因此它会进行无限递归。
您可以通过此程序确认这一点
>>> def getter():
... print("getter called")
... return 0
...
>>> {0: 1}.get(0, getter())
getter called
1
即使键 0 存在于字典中,由于将评估传递给 Python 中函数的所有参数,因此也会在生成实际的 dict.get 之前调用 getter。
如果您只想在已计算值时避免多次递归计算,则使用functools.lru_cache,如果您使用的是 Python 3.2+
>>> @functools.lru_cache()
... def fact(n):
... print("fact called with {}".format(n))
... if n == 0:
... return 1
... return n * fact(n-1)
...
>>> fact(3)
fact called with 3
fact called with 2
fact called with 1
fact called with 0
6
>>> fact(4)
fact called with 4
24
这个装饰器只是缓存传递参数的结果,如果再次进行相同的调用,它将简单地从缓存中返回值。
如果你想修复你的自定义缓存函数工作,那么你需要在函数外部定义look_up,这样当函数被调用时它就不会被创建。
>>> look_up = {0: 1}
>>> def fact(n):
... if n not in look_up:
... print("recursing when n is {}".format(n))
... look_up[n] = n * fact(n - 1)
... return look_up[n]
...
>>> fact(3)
recursing when n is 3
recursing when n is 2
recursing when n is 1
6
>>> fact(4)
recursing when n is 4
24
>>> fact(4)
24
否则你可以使用默认参数,像这样
>>> def fact(n, look_up={0: 1}):
... if n not in look_up:
... print("recursing when n is {}".format(n))
... look_up[n] = n * fact(n - 1)
... return look_up[n]