理解python中的递归::混乱

理解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存储在哪里 谢谢 每个递归的值都存储在调用堆栈中: 可以按如下方式显示函数的反汇编:

我试图理解递归

我有这段代码,它计算范围到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 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
,因为它包含了上限)。关于他的意图,我同意你的看法,我只是想给他一个怀疑的好处。我并没有把太多的精力放在命名约定上,而是试图为他简化递归——但你是对的,我应该用一些不那么模棱两可的东西。谢谢,斯蒂芬。