深度递归(Python)

Posted

技术标签:

【中文标题】深度递归(Python)【英文标题】:Recursion in depth (Python) 【发布时间】:2017-02-20 07:45:54 【问题描述】:

检查以下代码:

>>> def fib(x):
...    if x == 0 or x == 1:
...        return 1
...    else: 
...        return fib(x-1) + fib(x-2)
>>> print(fib(4))

根据 SoloLearn Python 教程(用于递归)中的 cmets,代码的工作方式如下:

1. fib(4) = fib(3) + fib(2)
2. = (fib(2) + fib(1)) + (fib(1) + fib(0))
3. = fib(1) + fib(0) + fib(1) + fib(1) + fib(0)
4. = 1+ 1 + 1 + 1 + 1
5. = 5

在第 2 行之后,只有 fib(2) 应该转到 fib() 函数的 else 部分,对吗? 两个fib(1) 和一个fib(0) 满足fib() 函数的if 部分的条件。所以返回 1。我的问题是,为什么在第 3 行中,fib(1) + fib(0) + fib(1) + fib(1) + fib(0) 都被替换为 1 然后添加?

请原谅我问了这么一个菜鸟问题。

【问题讨论】:

因为所有这些调用都解析为第一个子句。 【参考方案1】:

这是一个双递归函数,因此它的调用结果是一个调用树结构,基本情况为 fib(1) 和 fib(0)

fib(4) =                  fib(3)          +        fib(2)    
                         /      \                 /     \
fib(4) =        (  fib(2)   +    fib(1) ) + ( fib(1) + fib(0) )    
                  /     \         |              |        |
fib(4) = ( ( fib(1) + fib(0) ) + fib(1) ) + ( fib(1) + fib(0) )    
               |        |          |            |        |
fib(4) = ( (   1    +   1    ) +   1    ) + (   1    +   1    )    
                  \   /            |               \    /
fib(4) = ( (        2        ) +   1    ) + (        2        )    
                        \       /                    |
fib(4) = (                  3           ) + (        2        )    
                                   \             /
fib(4) =                                  5

您还可以通过在正确的位置添加一些打印和一个额外的辅助参数来帮助它和一些其他小的更改来可视化函数的工作

>>> def fib(n, nivel=0):
        if n==0 or n==1:
            print(" "*nivel,"fib(",n,")=1")
            return 1
        else:
            print(" "*nivel,"fib(",n,")")
            result = fib(n-1,nivel+1) + fib(n-2,nivel+1)
            print(" "*nivel,"fib(",n,")=",result)
            return result

>>> fib(4)
 fib( 4 )
  fib( 3 )
   fib( 2 )
    fib( 1 )=1
    fib( 0 )=1
   fib( 2 )= 2
   fib( 1 )=1
  fib( 3 )= 3
  fib( 2 )
   fib( 1 )=1
   fib( 0 )=1
  fib( 2 )= 2
 fib( 4 )= 5
5
>>> 

这里你可以注意到调用是按从左到右和自下而上的顺序解决的

【讨论】:

【参考方案2】:

我认为对代码工作原理的描述具有误导性,因为它似乎表明在从一行到下一行时并不是每个值都被评估。如果我们在下一行用它调用的函数(或它返回的值)替换所有内容,并在您的示例中放置括号,我们会得到以下内容,这可能有助于您更好地理解该代码的内部工作原理:

1. fib(4) 
2. = fib(3) + fib(2)
3. = (fib(2) + fib(1)) + (fib(1) + fib(0))
4. = ((fib(1) + fib(0)) + 1) + (1 + 1)
5. = 1 + 1 + 1 + 2
6. = 5

【讨论】:

为什么第 3 行的 fib(1) 被第 4 行的 1 替换了? 仍然不喜欢这种描述,因为对我来说它意味着某种并行化。现实情况是,在考虑下一个之前,第 2 行上的一个调用首先被探测到了它的深度。 @Ahnaf 因为如果你的递归中有if 子句!请参阅 Robert Columbia 的回答,并注意当您调用 fib(1) 时,参数 x 的值为 1。【参考方案3】:

@MorganThrapp 是正确的。更具体地说,递归函数fib 的基本情况是:

if x==0 or x==1:
    return 1

在调用fib(1)fib(0) 时触发该子句。在编程语言中,函数计算为其返回值,这里是1

在您的 fib(4) 示例中,fib 使用 10 输入被调用五次,这些结果全部相加,最终返回值为 5它从您对fib(4) 的原始调用返回并立即传递给print 函数。

【讨论】:

以上是关于深度递归(Python)的主要内容,如果未能解决你的问题,请参考以下文章

如何增加 Python 中的最大递归深度? [复制]

深度python字典递归

深度递归(Python)

Python:超出最大递归深度

Python递归函数错误:“超出最大递归深度” [重复]

Python:打印自定义异常时超出最大递归深度