Python函数参数评估模型
我在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评估模型的提示,这可能会帮助我理解。
谢谢!
1 个回答
4
当你把 fact
改成 n * fact(n-1)
时,循环永远不会结束的原因是 n * fact(n-1)
必须先计算(作为 if
的第三个参数)。这个计算会导致再次调用 fact
,这样就会一直重复下去(因为没有基础情况来停止它)。
之前,你传递的是一个函数对象(lambda
),这个对象不会在 if
的主体执行之前被计算,它的结果会通过 test
来检查。
这被称为“急切计算”,也就是函数的参数在传递给函数之前就被计算了。而在“懒惰计算”的情况下,参数只有在函数体内被使用时才会被计算。