我编写了一个Python函数来计算数字的阶乘,就像这样;
def fact(n):
return {0: 1}.get(n, n * fact(n-1))
我惊讶地发现,它导致了无限递归,即使对于fact(0)
也是如此。然后我添加了一个断言,就像这样;
def fact(n):
assert n >= 0
return {0: 1}.get(n, n * fact(n-1))
但这一次引发了AssertionError,这意味着n
变为负值。我不明白。我在网上查到了这个。但是,不幸的是,找不到任何答案。有人能向我解释一下这里发生了什么吗?
在Python中,函数调用使用"渴望"求值——在调用函数之前计算值,而不是在函数实际使用值时计算值。
因此,在中
{0: 1}.get(n, n * fact(n-1))
表达式n * fact(n-1)
在甚至调用get()
之前被求值。即,即使get((根本不需要该值,也会对表达式求值。这就是触发递归的原因。
dict.get(item, default=None)
只是一个接受1个或可选的两个参数的函数。如果传递n * fact(n-1)
作为默认值,则在传递该表达式之前会对其求值。整个
return {0: 1}.get(n, n * fact(n-1))
这个结构看起来有点做作。更简单的
return n * fact(n-1) if n else 1
同样简洁,并且只有在实际输入了各自的逻辑分支时才会对其进行求值。