> 文章列表 > python基础系列 —— 递归函数认知

python基础系列 —— 递归函数认知

python基础系列 —— 递归函数认知

目录

一、递归函数

1. 概念

2. 特点

3. 个人总结 

二、求任意数n的阶乘练习

1. 普通方法

2. 递归方法

 3. 尾递归方法

三、斐波那契数列练习

1. 递归写法


一、递归函数

1. 概念

        递归函数: 自己调用自己的函数是递归函数
        递是去,归是回,一去一回是递归

2. 特点

函数在运行的时候,需要内存开辟空间才可以,这个空间叫做栈帧空间

递归:
(1)去的过程就是不停的开辟栈帧空间,在回的时候,就是在不停的释放栈帧空间,
递归函数就是不停的开辟和释放栈帧空间的一个完整的过程
(2)回的时候有两种触发的机制,要么是最后一层函数空间全部执行完毕,要么是遇到return,都会触底反弹(回马枪).
(3)写递归函数时候,必须给与跳出的条件,如果递归的层数过多,不推荐使用,容易内存溢出或者蓝屏
(4)递归调用每一层空间都是独立的个体,独立的副本,资源不共享,可以通过return来完成值的传递

     官方说法,递归最大深度是1000层,具体按照机器来看

def deepfunc():deepfunc()报错:
[Previous line repeated 996 more times]

3. 个人总结 

递归就是一个函数调用自己的过程,一旦发现递归,就要考虑回的过程;递的过程只是寻找最终值或者return,不做任何结果输出,我们运算的结果主要是归的过程返回的值;就像在幽谷里面停回声。

二、求任意数n的阶乘练习

1. 普通方法

def func(n):total = 1for i in range(1,n+1):total *= i"""total = total * i => 1 * 1total = total * i => 1 * 1 * 2total = total * i => 1 * 1 * 2 * 3total = total * i => 1 * 1 * 2 * 3 * 4 total = total * i => 1 * 1 * 2 * 3 * 4 * 5"""return total
res = func(5) 
print(res)

2. 递归方法

def func(n):if n <= 1:return 1return n * func(n - 1)res = func(5)
print(res)
# 代码解析:
# 去的过程
n = 5  return 5 * func(5 - 1) => 5*func(4)
n = 4  return 4 * func(4 - 1) => 4*func(3)
n = 3  return 3 * func(3 - 1) => 3*func(2)
n = 2  return 2 * func(2 - 1) => 2*func(1)
n = 1  return 1# 回的过程
n = 2  return 2*func(1) => 2*1       [func(2)]
n = 3  return 3*func(2) => 3*2*1     [func(3)]
n = 4  return 4*func(3) => 4*3*2*1   [func(4)]
n = 5  return 5*func(4) => 5*4*3*2*1 [func(5)]
res = func(5) <=> 5*4*3*2*1 = 120
"""# 通俗点
看着这个式子,n=5时,不满足<=1,跳到func(n-1)中,开始计算func(4),依旧不满足,直到n=1,才可以直接return 1;
到达终点后开始反弹,回到2,得出return 2 * 1,回到3,得出3 * func(2)也就是3*2*1,以此类推

 3. 尾递归方法

递归是每层开辟一块空间,尾递归是特殊的递归,特点是直接在原空间上面开辟,无论调用多少次函数,都只占用一份空间
好处: 只需要考虑最后一层空间的结果是多少,就不用额外考虑回的过程了;
注意:尾递归需要把值放到参数中运算

def jiecheng(n,endval=1):if n <= 1:return endval	return jiecheng(n-1, endval*n)
print(jiecheng(5))
# 代码解析:
# 去的过程
n = 5,endval = 1  return jiecheng(5-1,endval*n ) => return jiecheng(4,1*5)
n = 4,endval = 1*5return jiecheng(4-1,endval*n ) => return jiecheng(3,1*5*4)
n = 3,endval = 1*5*4return jiecheng(3-1,endval*n ) => return jiecheng(2,1*5*4*3)
n = 2,endval = 1*5*4*3return jiecheng(2-1,endval*n ) => return jiecheng(1,1*5*4*3*2)
n = 1,endval = 1*5*4*3*2if 1 <= 1  条件满足 return endval => return 1*5*4*3*2# 回的过程
n = 2  return 1*5*4*3*2
n = 3  return 1*5*4*3*2
n = 4  return 1*5*4*3*2
n = 5  return 1*5*4*3*2
到此程序全部结束;
"""为什么尾递归不需要考虑回的过程呢,因为函数目的是return endval,而endval的值已经在计算过程中出来了,即使返回上一层,程序会默认目的已达成,继续返回。
为什么要参数默认写死endval=1呢,因为阶乘就是1*2*。。。这种格式,我们需要给一个初始值,意味着这个1不是固定的,是根据实际情况来,写死也是为了用户只关注n的值即可

三、斐波那契数列练习

1. 递归写法

def feb(n):if n ==1 or n == 2:return 1# 当前值n = 上一个值(n-1) + 上上个值(n-2)return feb(n-1) + feb(n-2)res = feb(5)
print(res)

#代码解析:
斐波那契数列的定义是:第一个数为1,第二个数为1,从第三个数开始,每个数均为前两个数之和。n = 5 
return feb(4) + feb(3)feb(3) + feb(2) + feb(3)feb(2) + feb(1) + feb(2) + feb(3)feb(2) + feb(1) + feb(2) + feb(2) + feb(1)1+1+1+1+1=5首先,我们将函数调用 feb(5) 传入参数5。
在函数内部,我们首先判断n的值是否等于1或2。由于5不等于1或2,所以我们将跳过这个条件语句。接下来,我们将执行这行代码 return feb(n-1) + feb(n-2),由于n等于5,因
此时我们需要求出斐波那契数列的第5个数。根据斐波那契数列的定义,第5个数应该是前两个数之和,即第4个数和第3个数之和。然后,我们需要计算 feb(4) 和 feb(3) 的值。首先,我们将调用 feb(4)。
在 feb(4) 函数内部,我们也需要计算斐波那契数列的第4个数,即第3个数和第2个数之和。因此,我们需要调用 feb(3) 和 feb(2) 来计算这个值。在 feb(3) 函数内部,我们需要计算斐波那
那契数列的第3个数,即第2个数和第1个数之和。因此,我们需要调用 feb(2) 和 feb(1) 来计算这个值。在 feb(2) 函数内部,由于 n 的值等于2,因此我们将直接返回1。在 feb(1) 函数内部,由于 n 的值等于1,因此我们也将直接返回1。现在,我们已经得到了 feb(2) 和 feb(1) 的值,因此我们可以计算 feb(3) 的值。根据斐波那契数列的定义,第3个数应该是前两个数之和,即1+1=2。因此,feb(3) 的返回值为2。接下来,我们已经得到了 feb(3) 和 feb(2) 的值,因此我们可以计算 feb(4) 的值。根据斐波那契数列的定义,第4个数应该是前两个数之和,即2+1=3。因此,feb(4) 的返回值为3。现在,我们已经得到了 feb(4) 和 feb(3) 的值,因此我们可以计算 feb(5) 的值。根据斐波那契数列的定义,第5个数应该是前两个数之和,即3+2=5。因此,feb(5) 的返回值为5。最后,我们在主函数中将 feb(5) 的返回值打印出来,结果为5。
因此,这段代码的执行过程可以总结如下:调用 feb(5) 函数来计算斐波那契数列的第5个数。feb(5) 函数内部调用 feb(4) 和 feb(3) 函数来计算斐波那契数列的第4个数和第3个数。feb(4) 函数内部调用 feb(3) 和 feb(2) 函数来计算斐波那契数列的第3个数和第2个数。feb(3) 函数内部调用 feb(2) 和 feb(1) 函数来计算斐波那契数列的第2个数和第1个数。feb(2) 函数内部直接返回值1。feb(1) 函数内部直接返回值1。feb(3) 函数内部得到 feb(2) 和 feb(1) 的返回值后,计算斐波那契数列的第3个数为2。feb(4) 函数内部得到 feb(3) 和 feb(2) 的返回值后,计算斐波那契数列的第4个数为3。feb(5) 函数内部得到 feb(4) 和 feb(3) 的返回值后,计算斐波那契数列的第5个数为5。主函数将 feb(5) 的返回值打印出来,结果为5。