Python递归函数-这里发生了什么?

Python递归函数-这里发生了什么?,python,function,recursion,factorial,Python,Function,Recursion,Factorial,我用python编写了一个简单的阶乘函数,并嵌入了一系列调试代码,以帮助我理解正在发生的事情。然而,输出让我更加困惑。有人能帮我理解吗?(顺便说一句,如果出现打印输出定时问题,我运行了几次,但得到的输出完全相同。) 递归函数.py def recursive(n): if n == 1: return 1 print ('n : {}'.format(n)) print ('recursive return value is: {}'.format(n*recursive(n

我用python编写了一个简单的阶乘函数,并嵌入了一系列调试代码,以帮助我理解正在发生的事情。然而,输出让我更加困惑。有人能帮我理解吗?(顺便说一句,如果出现打印输出定时问题,我运行了几次,但得到的输出完全相同。)

递归函数.py

def recursive(n):
  if n == 1:
    return 1
  print ('n : {}'.format(n))
  print ('recursive return value is: {}'.format(n*recursive(n-1)))
  return n*recursive(n-1)

x = recursive(5)
print('***** End result is: {}'.format(x))
(带行号)

(不带行号的清洁剂输出)


您的代码并不适合递归begginer,因此我在这里附加了另一个代码,它输出与您相同的值,但更容易理解

def重现(n):
如果n==1:
返回n
其他:
返回n*重复出现(n-1)
num=int(输入(“输入一个数字:”)
如果num<0:
打印(“对不起,负数不存在阶乘”)
elif num==0:
打印(“0的阶乘是1”)
其他:
print(“num”的阶乘,is,recur(num))
recur
函数将自然数n作为输入。如果n=1,这意味着1!=1,这应该是输出,没什么大不了的。 否则,函数将返回您的编号n*recur(n-1)。 例如:

——取n=4
n=1->false
现在返回(4)*重复(3)
(3) *复发(2)
(2) *复发(1)
现在n=1并返回(1)
括号()中的所有数字都将添加到整个乘积中,因此4*3*2*1=24。它之所以被称为递归,不是因为它调用自身,而是因为它向后启动:)) 希望我能让你轻松一点

额外提示:

如果n==1:
返回n

在这里,您可以将
返回n
替换为
返回1
,将具有相同的输出

该函数获取一个数字并计算结果

因此,对于
5
的值,结果是
5*4*3*2
,即
120

使该函数成为递归函数是有意义的,因为5的阶乘是4的阶乘的5倍,4的阶乘是3的阶乘的4倍,依此类推。如果调用函数时使用
n=1
,阶乘只返回为
1
,递归可以停止

将此视为此处运行的实际算法:

  • 5的阶乘=5*4的阶乘
  • 4的阶乘=4*3的阶乘
  • 3的阶乘=3*2的阶乘
  • 2的阶乘=2*1的阶乘
  • 1的阶乘=1

  • 可能有帮助的版本:

    def recursive(n):
      if n == 1:
        return 1
      print ('n : {}'.format(n))
      res = recursive(n-1)
      print ('return value is: {} (n={} * recursive({})={})'.format(n*res, n, n-1, res))
      return res * n
    
    x = recursive(5)
    print('***** End result is: {}'.format(x))
    
    变化:

    • 不要做两次递归调用
    • 在打印中添加了更多调试输出
    输出:

    n : 5
    n : 4
    n : 3
    n : 2
    return value is: 2 (n=2 * recursive(1)=1)
    return value is: 6 (n=3 * recursive(2)=2)
    return value is: 24 (n=4 * recursive(3)=6)
    return value is: 120 (n=5 * recursive(4)=24)
    ***** End result is: 120
    
    这是一个非常简单的例子,但是,复杂的递归方法可能会使任何人感到困惑。我发现,在每次通话(及其打印的信息)上打标签有助于我了解发生了什么。为此,只需在每次调用中向下传递递归级别(
    l
    ):

    def recursive(n, l=0):
      # l is the recurcion level
      if n == 1:
        return 1
      print ('{} n : {}'.format(l * "  ", n))
      res = recursive(n-1, l + 1)
      print ('{} return value is: {} (n={} * recursive({})={})'.format(
        l * "  ", n * res, n, n-1, res)
      )
      return res*n
    
    现在可以稍微格式化一些内容:

     n : 5
       n : 4
         n : 3
           n : 2
           return value is: 2 (n=2 * recursive(1)=1)
         return value is: 6 (n=3 * recursive(2)=2)
       return value is: 24 (n=4 * recursive(3)=6)
     return value is: 120 (n=5 * recursive(4)=24)
    ***** End result is: 120
    

    下面是一个查找整数阶乘的递归函数示例

    def calc_factorial(x):
        """This is a recursive function
        to find the factorial of an integer"""
    
        if x == 1:
            return 1
        else:
            return (x * calc_factorial(x-1))
    
    num = 4
    print("The factorial of", num, "is", calc_factorial(num))
    
    上面的例子,
    calc\u factorial()
    是一个调用自身的递归函数

    当我们用一个正整数调用这个函数时,它将通过减少这个数递归地调用自己

    每个函数调用将数字乘以数字的阶乘1,直到数字等于1。这个递归调用可以在以下步骤中解释

    calc_factorial(4)              # 1st call with 4
    4 * calc_factorial(3)          # 2nd call with 3
    4 * 3 * calc_factorial(2)      # 3rd call with 2
    4 * 3 * 2 * calc_factorial(1)  # 4th call with 1
    4 * 3 * 2 * 1                  # return from 4th call as number=1
    4 * 3 * 2                      # return from 3rd call
    4 * 6                          # return from 2nd call
    24                             # return from 1st call
    
    当数字减少到1时,我们的递归结束。这称为基本条件

    每个递归函数必须有一个停止递归的基本条件,否则函数将无限地调用自身

    另一个例子 递归函数通常有两个组件:

    • 基本情况是确定递归函数何时停止的条件
    • 对自己的呼唤 以下是演示这两个组件的示例:
    对于我们来说,基本情况是剩余变量是否等于
    0
    ,即我们必须打印多少剩余的“hi”字符串。该函数只返回

    在print语句之后,我们再次调用
    hi\u recursive
    ,但剩余值减少。这很重要!如果我们不减少剩余值,函数将无限期运行。通常,当递归函数调用自身时,参数会更改为更接近基本情况

    让我们想象一下当我们调用hi\u recursive(3)
    时它是如何工作的:


    在函数打印“
    hi
    ”之后,它会使用一个较低的值调用自身,以便在达到
    0
    之前保持该值。在0处,函数返回到在
    中调用它的位置,返回到在

    一件非常有用的事情就是不要重复递归!在第二次打印中,您执行了
    n*recursive(n-1)
    ,这实际上调用了相同的方法,并将输出搞砸了!而是保存结果并打印/返回:
    res=n*递归(n-1);打印(f“递归结果{res}”);return res
    (你的问题是什么?问“为什么这样做”并没有问任何问题,真的。这就是它所做的。你不明白什么?”urban,你是对的,我完全弄糊涂了。谢谢你的建议。更新答案(sry忘了删除重复呼叫!)您的第一个示例仍然具有对递归的双重调用
    def calc_factorial(x):
        """This is a recursive function
        to find the factorial of an integer"""
    
        if x == 1:
            return 1
        else:
            return (x * calc_factorial(x-1))
    
    num = 4
    print("The factorial of", num, "is", calc_factorial(num))
    
    calc_factorial(4)              # 1st call with 4
    4 * calc_factorial(3)          # 2nd call with 3
    4 * 3 * calc_factorial(2)      # 3rd call with 2
    4 * 3 * 2 * calc_factorial(1)  # 4th call with 1
    4 * 3 * 2 * 1                  # return from 4th call as number=1
    4 * 3 * 2                      # return from 3rd call
    4 * 6                          # return from 2nd call
    24                             # return from 1st call
    
    # Assume that remaining is a positive integer
    
        def hi_recursive(remaining):
            # The base case
            if remaining == 0:
                return
            print('hi')
        
            # Call to function, with a reduced remaining count
            hi_recursive(remaining - 1)