【问题标题】:The logic of if statement with recursive function in PythonPython中带有递归函数的if语句的逻辑
【发布时间】:2018-07-27 21:32:09
【问题描述】:

我有以下简单的递归函数:

def draw_interval(center_length):
    if center_length > 0: 
        print('first value: {}'.format(center_length))
        draw_interval(center_length - 1)      
        print('second value: {}'.format(center_length))              

draw_interval(3)

输出是:

first value: 3
first value: 2
first value: 1
second value: 1
second value: 2
second value: 3

我的问题是为什么会这样,即使在 center_length > 0 之后,函数也会运行 draw_interval(center_length - 1) 错误的。我已经看到了similar question,但我的问题指向 Python 中递归功能和条件语句的不同角度。

【问题讨论】:

  • 我不确定我是否理解您的问题。你会假设其他什么行为?
  • “即使在center_length > 0 为假之后,函数也会运行draw_interval(center_length - 1):你为什么这么认为?事实并非如此。
  • 如果条件为真,If 语句块运行,我猜,但在打印第一个值:1 后,它继续运行。我在这里遗漏了一些要点吗?
  • 值得将您的代码粘贴到 PythonTutor.com 或其他交互式可视化工具中——或者只使用调试器,如果你知道怎么做的话——并逐步进行。一切都应该从此变得更加清晰,比任何人都可以抽象地解释的任何事情都要清楚。

标签: python if-statement recursion data-structures


【解决方案1】:

这就是你的函数的递归方式:

draw_interval(3):
    center_length > 0 is true
    "first value 3"
    draw_interval(2):
        center_length > 0 is true
        "first value 2"
        draw_interval(1):
            center_length > 0 is true
            "first value 1"
            draw_interval(0):
                center_length > 0 is FALSE: no more calls to `draw_interval` are made
                execution returns to draw_interval(1)
            "second value 1"
            execution returns to draw_interval(2)
        "second value 2"
        execution returns to draw_interval(3)
    "second value 3"
    execution returns to the end of your program

它确实center_length > 0 为False 之后运行draw_interval(center_length - 1)

【讨论】:

  • 为什么在 FALSE 行之后,执行返回到 draw_interval(1) ?
  • @mk_sch 因为函数执行完毕后,执行返回函数被调用的地方。这就是函数的工作原理。
  • 我还是没有得到答案。我在pythontutor.com 中可视化了代码,但也没有帮助。
【解决方案2】:

让我们一步一步地运行你的代码 -

def draw_interval(center_length):
    if center_length > 0: 
        print('first value: {}'.format(center_length))
        draw_interval(center_length - 1)      
        print('second value: {}'.format(center_length))              
draw_interval(3)

print('first value: {}'.format(center_length)) comes here, 
prints 3

draw_interval(center_length - 1) => draw_interval(2) called
1. print('second value: {}'.format(center_length)) stays in memory because draw_interval() called with 2

draw_interval(2)
print('first value: {}'.format(center_length)) comes here, 
prints 2
2. print('second value: {}'.format(center_length)) stays in memory because draw_interval() called with 1

draw_interval(1)
print('first value: {}'.format(center_length)) comes here, 
prints 1
3. print('second value: {}'.format(center_length)) stays in memory because draw_interval() called with 0

条件为假 解开步骤 3、2、1 打印 1、2、3

希望这是有道理的

【讨论】:

  • 我很难理解留在内存中的数字,当调用递归函数时,不是更清楚。
【解决方案3】:

您似乎希望输出在前三行输出之后停止。

但是if主体虽然没有第四次执行,但整体执行并没有停止。仍然有一个不为空的调用堆栈。那个特定的函数调用(没有执行if 块),返回到调用它的函数的执行上下文,它还有事情要做。也就是说,它应该打印“第二个值”......然后它也返回到它被调用的地方,......等等。

请注意,当一个函数被调用时(可能是从一个函数内部——可能是同一个函数),调用代码将在该函数返回后恢复。在您的情况下,代码在 if 块中返回,其中的条件没有被重新评估,就像之前已经完成的那样。所以即使center_length 变为 0,它也不会影响调用代码将继续执行的位置。

更重要的是,每个函数执行上下文都有自己独立的center_length 变量。因此,即使它以减一的形式传递,这也不会影响 center_length 在调用函数中的值。这一事实不会影响您案例中的执行顺序,但它可能有助于掌握递归。

【讨论】:

    【解决方案4】:

    之所以如此,是因为递归创建了嵌套函数并从上到下然后以相反的顺序返回。这就是我的意思:

    draw_interval(3):
        if 3 > 0:
            print('first: ', 3)
            if 2 > 0:
                print('first: ', 2)
                if 1 > 0:
                    print('first: 1')
                    if 0 > 0:            # this doesn't pass
                        print('first: 0') 
                        print('second: 0')
                    print('second: 1')
                print('second: 2')
            print('second: 3')
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-15
      • 2016-01-30
      相关资源
      最近更新 更多