理解python中的递归::混乱
我试图理解递归 我有这段代码,它计算范围到2个数字之间的和理解python中的递归::混乱,python,Python,我试图理解递归 我有这段代码,它计算范围到2个数字之间的和 def sum(lower, upper): if lower > upper: return 0 else: return lower + sum(lower +1, upper) print(sum(11, 30)) 我试图理解每个递归调用的值存储在哪里。 如果下限是12,上限是30,那么42存储在哪里 谢谢 每个递归的值都存储在调用堆栈中: 可以按如下方式显示函数的反汇编:
def sum(lower, upper):
if lower > upper:
return 0
else:
return lower + sum(lower +1, upper)
print(sum(11, 30))
我试图理解每个递归调用的值存储在哪里。
如果下限是12,上限是30,那么42存储在哪里
谢谢
每个递归的值都存储在调用堆栈中: 可以按如下方式显示函数的反汇编:
def my_sum(lower, upper):
if lower > upper:
return 0
else:
return lower + my_sum(lower +1, upper)
import dis
dis.dis(my_sum)
你会得到:
2 0 LOAD_FAST 0 (lower)
2 LOAD_FAST 1 (upper)
4 COMPARE_OP 4 (>)
6 POP_JUMP_IF_FALSE 12
3 8 LOAD_CONST 1 (0)
10 RETURN_VALUE
5 >> 12 LOAD_FAST 0 (lower)
14 LOAD_GLOBAL 0 (my_sum)
16 LOAD_FAST 0 (lower)
18 LOAD_CONST 2 (1)
20 BINARY_ADD
22 LOAD_FAST 1 (upper)
24 CALL_FUNCTION 2
26 BINARY_ADD
28 RETURN_VALUE
30 LOAD_CONST 0 (None)
32 RETURN_VALUE
LOAD\ U FAST例程从函数堆栈中加载值
这与临时值相同。Python和大多数其他语言使用称为堆栈的结构进行函数调用。如果您不熟悉,我建议您仔细阅读。它将使您对stack的工作方式有一个坚实的了解
我建议退房 您的代码使用不同的命名约定编写
def compute(low, high):
if low > high:
return 0
else:
return low + compute(low+1, high)
给定一个整数(低)和另一个高于所述整数(高)的整数,此代码将通过递归找到这两个整数(包括)之间的和
e、 g.>>计算(6,9)
上面将通过递归的方式返回30,即每次不满足初始条件时,如果低>高:
,将再次调用该函数,将1添加到低,以便最终满足条件,当满足条件时(当低等于10时),将设置递归
仍然使用示例compute(6,9)
-当low=10时,返回0,以前的low是9,因此表达式return low+compute(low+1,high)
此时将是return 9+0
,现在转到下一个递归调用,9之前的low是8-我们刚刚从上一个调用返回了9,所以return 8+9
,返回17。。。我想你明白了,这个过程一直持续到最初的return语句。可以把它想象成解开一条紧身裤,然后让它回到最初的形状
请注意,如果没有最终满足的第一个条件和递增返回语句,函数将无限地返回相同的内容,因此如果永远不满足条件,则,或者无限地将1添加到low
我希望这对递归有点启发。把它想象成一个呼叫中心。一个广告,他们告诉你一个范围内的数字的总和,你可以要求
所以你打电话给那里的某个人,询问12到30之间的数字之和。那个人认为“该死,这对我来说太复杂了”,于是打电话给同一个呼叫中心,要求从13点到30点。第二个人仍然不能直接做这件事,于是再次打电话给中心,要求14到30美元的金额。等等最终有人会接到一个电话,要求从31到30的总和,并直接回答“嗯,这是一个空范围,所以当然是零”。然后一切都倒退了。所有参与调用堆栈的人,一直在等待他们的答案,现在一个接一个地计算他们自己的结果并报告给调用他们的人。所以答案是“30”(因为30+0),然后是“59”(因为29+30),然后是“87”(因为28+59),依此类推。最终,你打电话要求12到30的人会得到答案,13到30的总和是387。他们把它加到12,然后回复你“399”
在这个类比中,有些人在等待自己的答案时,将请求数据保存在头脑中。当在计算机编程中完成时,所有这些数据存储在哪里?嗯,在路上。它被称为堆栈,因为就像一堆文件,你一次构建一个,然后一次取下一个,调用是在彼此的顶部进行的,并以相反的顺序完成。就像呼叫中心一样,计算机的呼叫堆栈大小有限。当你询问的范围大于呼叫中心的人数时,最终呼叫中心的每个人都会参与到你的请求中,最后一个打电话的人将没有人可以交谈。在这一点上,系统有些崩溃。在计算机中,这被称为“堆栈溢出”。就像这个网站。只是一个评论:sum
是一个:你应该选择一个不同的名字…42?那是从哪里来的?这不是所有问题的答案。有了上面和下面的代码,在任何地方都不会有42个。要真正理解这一点,你需要看看调用堆栈是如何工作的。是的,我之前没有看过代码。有几个flaws@JasonAruni嗯?不,那你不能加12和30。你把12和13到30的数字相加,也就是说,你把12和387相加。我误读了第二行。。。答复已被编辑。然而,这仍然是一个不正确的说法——我相信他有意将最初的论点排除在总数之外。我认为有很多人在表示包容性时会说“介于之间”。这让我很烦,但事实就是这样。我怀疑他“有意”做什么。这听起来像是他写的代码,我肯定他没有。顺便说一句,“compute”也是个坏名字,因为它非常通用。我可能会称之为“rangesum”(唯一的缺点是,它不等同于Python的range
,因为它包含了上限)。关于他的意图,我同意你的看法,我只是想给他一个怀疑的好处。我并没有把太多的精力放在命名约定上,而是试图为他简化递归——但你是对的,我应该用一些不那么模棱两可的东西。谢谢,斯蒂芬。