不了解递归函数的工作原理很常见,但这确实表明您只是不了解函数和返回的工作原理,因为递归函数的工作原理与普通函数完全相同。
print 4
这是有效的,因为该print
语句知道如何打印值。它被赋予了 value 4
,并打印出来。
print 3 + 1
该print
语句不理解如何打印3 + 1
。3 + 1
不是一个值,它是一个表达式。幸运print
的是不需要知道如何打印表达式,因为它永远不会看到它。Python 将值传递给事物,而不是表达式。所以 Python 所做的就是在执行代码时评估表达式。在这种情况下,这会4
产生价值。然后将该值4
赋予该print
语句,该语句愉快地打印它。
def f(x):
return x + 1
print f(3)
这与上面的非常相似。f(3)
是一个表达式,而不是一个值。print
不能用它做任何事情。Python 必须对表达式求值以产生一个值来打印。它通过查找 name 来做到这一点,f
幸运的是,它找到了由def
语句创建的函数对象,并使用参数调用函数3
。
这导致函数的主体被执行,并x
绑定到3
. 与 的情况一样print
,该return
语句不能对表达式执行任何操作x + 1
,因此 Python 会评估该表达式以尝试找到一个值。x + 1
with x
bound to3
产生 value 4
,然后返回。
从函数返回一个值会使函数调用表达式的求值变为该值。所以,回到 中print f(3)
,Python 已经成功地将表达式计算f(3)
为 value 4
。然后print
可以打印。
def f(x):
return x + 2
def g(y):
return f(y * 2)
print g(1)
这里又g(2)
是一个表达式而不是一个值,所以它需要被评估。评估g(2)
导致我们f(y * 2)
有y
约束力1
。y * 2
不是一个值,所以我们不能调用f
它;我们必须首先评估它,这会产生 value 2
。然后我们可以调用f
on ,2
它返回bound to 。计算为 value ,该 value 是从内部返回并成为内部表达式的值。这最终给出了一个返回值,因此表达式被评估为 value ,然后打印出来。x + 2
x
2
x + 2
4
f
f(y * 2)
g
g
g(1)
4
请注意,在深入评估f(2)
Python 时,仍然“记得”它已经在评估的中间,g(1)
一旦知道f(2)
评估的内容,它就会回到正确的位置。
就是这样。这就是全部。您不需要了解有关递归函数的任何特殊内容。return
使调用此特定函数调用的表达式成为赋予的值return
。直接表达式,而不是调用函数的更高级别的表达式调用函数的函数。最里面的一个。中间函数调用是否恰好与这个函数调用相同的函数并不重要。甚至无法return
知道此函数是否被递归调用,更不用说在这两种情况下的行为不同了。return
总是总是将其值返回给直接这个函数的调用者,不管它是什么。它永远不会“跳过”任何这些步骤并将值返回给更远的调用者(例如递归函数的最外层调用者)。
但为了帮助您了解这是否有效,让我们fib(3)
更详细地跟踪评估。
fib(3):
3 is not equal to 0 or equal to 1
need to evaluate fib(3 - 1) + fib(3 - 2)
3 - 1 is 2
fib(2):
2 is not equal to 0 or equal to 1
need to evaluate fib(2 - 1) + fib(2 - 2)
2 - 1 is 1
fib(1):
1 is equal to 0 or equal to 1
return 1
fib(1) is 1
2 - 2 is 0
fib(0):
0 is equal to 0 or equal to 1
return 1
fib(0) is 1
so fib(2 - 1) + fib(2 - 2) is 1 + 1
fib(2) is 2
3 - 2 is 1
fib(1):
1 is equal to 0 or equal to 1
return 1
fib(1) is 1
so fib(3 - 1) + fib(3 - 2) is 2 + 1
fib(3) is 3
更简洁地说,fib(3)
返回fib(2) + fib(1)
。fib(1)
返回 1,但fib(3)
返回1加上的结果fib(2)
。fib(2)
返回fib(1) + fib(0)
;两者都返回1
,因此将它们加在一起fib(2)
得到2
. 回到fib(3)
过去fib(2) + fib(1)
,我们现在可以说这就是2 + 1
过去3
。
您缺少的关键点是 whilefib(0)
或fib(1)
return 1
,它们1
构成了更高级别调用相加的表达式的一部分。