我正在查看Peter Norvig网站上的一篇文章,他试图回答以下问题(这不是我的问题,顺便说一句) “我可以在Python中做相同的(test?result:alternative)吗?”
这是他列出的选项之一,
def if_(test, result, alternative=None):
"If test is true, 'do' result, else alternative. 'Do' means call if callable."
if test:
if callable(result): result = result()
return result
else:
if callable(alternative): alternative = alternative()
return alternative
这是一个用法示例。
>>> fact = lambda n: if_(n <= 1, 1, lambda: n * fact(n-1))
>>> fact(6)
720
我理解这是如何工作的(我想),但我只是在玩代码,并决定看看当我在上面的'fact'定义中改变第三个参数时会发生什么 n * fact(n-1),即将其更改为不可调用的表达式。在运行它时,解释器进入一个永无止境的循环。我非常清楚为什么会发生这种情况,也就是说,if_函数返回的是它接收的相同表达式。但那个表达的类型是什么?到底发生了什么?我不是在寻找详细的解释,只是为了一些指向python评估模型的指针,这可能有助于我理解。
谢谢!
答案 0 :(得分:4)
当您将fact
更改为n * fact(n-1)
时,循环永不终止的原因是n * fact(n-1)
必须先评估(作为if
的第三个参数)。评估它会导致另一个fact
的无限通话(因为不再有任何基本情况可以阻止它)。
以前,您传递了一个函数对象(lambda
),在if
的正文之前不会对其进行求值,并且会通过test
检查其结果。
这是众所周知的(我相信)作为热切评估,其中函数参数在传递给函数之前进行评估。在惰性求值方案中,在函数体中使用参数之前,不会对参数进行求值。