Python递归思想与代码实现

article/2025/10/24 16:27:59

1, 递归思想

递归算法:递归(Recursion),在数学与计算机科学中,是指在函数的定义中使用函数自身的方法。

这是官方的解释,翻译成人话就是:

  • 函数内部自己调用自己
  • 函数必须有出口 

函数自己调用自己很好理解,但什么是出口呢?我们知道,递归实际上是简化嵌套for循环的一种精简算法,所以在函数内部自己调用自己的过程就是在不短的循环,并改变函数传入的参数。如果没有不再执行自己调用自己的出口,那么递归就会陷入无限循环的无底洞。

出口通常是用return或if else语句避免再调用自己。

def recursion(n):print(n, "<===1====>")if n > 0:recursion(n - 1)# 那么这就是一个出口,如果n <= 0了就会不再递归else:print(n, '<===2====>')recursion(5) # 外部调用

结果就是:


5 <===1====>
4 <===1====>
3 <===1====>
2 <===1====>
1 <===1====>
0 <===1====>
0 <===2====>  # 这个是出口,在这个时候n = 0Process finished with exit code 0

递归还有两个重要的思想,第一个我们要找到等价的运算式,也就是将大问题拆分成很多个可递归的小问题。

第二个:

  1. 递推:像上边递归实现所拆解,递归每一次都是基于上一次进行下一次的执行,这叫递推。
  2. 回溯:则是在遇到终止条件,则从最后往回返一级一级的把值返回来,这叫回溯。

听到这是不是有点懵,我们来通过下面阶乘的实例与代码实现来进一步理解这个思想。

2,递归求阶乘,代码实现与思想解析

首先先上代码:

def factorial(n):# 出口if n == 1:return 1else:return n * factorial(n-1)print(factorial(5))

这段代码求出了5的阶乘,大家先试着理解。

其中出口就是在n - 1 = 1的时候,递归就开始了回溯。

我们看一下流程图:

n * factorial(n-1)是等价表达式。红色箭头是递推的过程,从1-2-3-4;绿色箭头是回溯的过程,从a-b-c-d;紫色箭头是参数的变化。我把每一个式子都分解了一下,我们可以发现最后真正输出的是最外层的return,回溯顺序是从最底层往上返回。 

如果我们改一下代码,在每一次回溯的时候输出等价表达式的值:

def factorial(n):# 出口if n == 1:return 1# 递归内层else:factor = n * factorial(n-1)print(factor)return factorprint(factorial(5))

输出:

2
6
24
120
120Process finished with exit code 0

不难发现,第一个输出的2就是流程图中的a式的值,6是b式的值,24是c式的值,120就是d式也就是最外层返回的5的阶乘了。

通过此输出,也证明了回溯过程的实现。这样我们就可以利用此思想求斐波那契数列等等等。那么递归其实也是可以用for来实现的。

# 求5的阶乘
num = 1
for i in range(1,6):num *= i
print(num)

3,栈溢出

递归效率不高,递归层次过多会导致栈溢出(在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出),此时程序会抛出错误:超出最大递归深度。

那么一般最大的深度是1000左右,我们可以通过sys的两个方法来设置最大深度和得到最大深度。

import sys# 得到最大的深度值
print(sys.getrecursionlimit())
# 设置最大深度为2000
sys.setrecursionlimit(2000)

4,运行速度

import sys
import time
print(sys.getrecursionlimit())
sys.setrecursionlimit(2000)
start = time.time()def factorial(n):# 出口if n == 1:return 1# 递归内层else:return n * factorial(n-1)print(factorial(1000))
print(time.time() - start)

我们通过time方法来获取运行的时间,发现大概在0.008s左右

而for循环实测在0.004秒左右,所以我们看到递归的缺点是资源占用和运行速度劣与for循环。

所以我们总结一下递归的缺点:

  1. 递归由于是函数调用自身,而函数调用是有时间和空间的消耗的--效率
  2. 递归中很多计算都是重复的,由于其本质是把一个问题分解成两个或者多个小问题,多个小问题存在相互重叠的部分,则存在重复计算--效率
  3. 调用栈可能会溢出,其实每一次函数调用会在内存栈中分配空间,而每个进程的栈的容量是有限的,当调用的层次太多时,就会超出栈的容量,从而导致栈溢出,强制设置最大深度会导致内存占用大--性能

优点:

  1. 简洁
  2. 在特殊情况下比for循环更加简洁,逻辑清晰。

4,建议

在使用for循环运算量并不太大时使用递归,在for循环逻辑太过于繁琐时使用递归。

  


http://chatgpt.dhexx.cn/article/c2328O7B.shtml

相关文章

python函数递归调用时对深度没有限制_python递归深度

广告关闭 腾讯云11.11云上盛惠 ,精选热门产品助力上云,云服务器首年88元起,买的越多返的越多,最高返5000元! 今天在写爬虫的时候,发现了一个事情,使用str方法强制转换一个beautifulsoup对象成字符串的时候报错了,提示是“maximum recursion depth exceeded while cal…

python递归函数详解

python递归函数是指一个函数从一个状态开始&#xff0c;然后返回另一个状态。递归函数是在实现过程中遇到的最基本的一类函数。比如&#xff0c; int i0; int j0; int c1;等等都是一类递归函数&#xff0c;但是我们知道&#xff0c;它们在实现过程中需要执行多次&#xff0c;并…

Python 递归的优化

文章目录 前言一、递归实现斐波那契二、优化后的斐波那契总结 前言 递归&#xff0c;很常见的一种算法&#xff0c;在初学的时候我们都会用递归来解决斐波那契数列&#xff0c;但递归本身有非常大的缺陷&#xff0c;就是时间和空间占用都非常大&#xff0c;在进阶学习后&#…

Python 递归实现乘法

Python定义函数:使用递归求乘积&#xff08;x*y&#xff09; 1 当作x个y相加或者y个x相加 2 当其中一数&#xff08;以x为例&#xff09;不为1时&#xff0c;返回y加上该函数&#xff0c;同时每次x-1&#xff0c;直至x1为止&#xff0c;此过程实现了x个y相加 具体代码如下:

python递归遍历查询文件 文件夹

文章目录 &#x1f357;先看运行效果&#x1f354; 具体思路&#x1f35f; 一、主要使用的模块以及方法&#x1f32d; 二、主要思路以及代码&#x1f37f; 1、开始位置&#x1f9c2; 2、关键位置&#x1f953; 3、结果输出 &#x1f9c7; 完整源码&#x1f95e; 结尾&#x1f9…

轻松搞懂Python递归函数的原理与应用

递归: 在函数的定义中&#xff0c;函数内部的语句调用函数本身。 1、递归的原理 学习任何计算机语言过程中&#xff0c;“递归”一直是所有人心中的疼。不知你是否听过这个冷笑话&#xff1a;“一个面包&#xff0c;走着走着饿了&#xff0c;于是就把自己吃了”。 常理推断&…

python递归如何理解

最近在做递归一些相关的东西&#xff0c;发现递归入门很容易&#xff0c;但要具体了解其实现过程&#xff0c;比较难以理解&#xff0c;在这里将自己这几天的摸索记录一下&#xff0c;写知乎的主要目的是为了给自己做笔记&#xff0c;在做笔记的同时&#xff0c;帮助后来人少走…

【Python函数的递归】

递归的定义 函数作为一种代码封装&#xff0c;可以被其他程序调用&#xff0c;当然&#xff0c;也可以被函数内部代码调用。这种函数定义中调用函数自身的方式称为递归。就像一个人站在装满镜子的房间中&#xff0c;看到的影像就是递归的结果。递归在数学和计算机应用上非常强大…

H3C 交换机S5130S软件版本升级

1.通过官网下载软件包 升级的包名为 S5130S_HI-CMW710-R6330.ipe 2. 查看FLASH空间是否足够 <H3C>dir /all Free的空间需要是软件包的2倍大小&#xff0c;例如S5130S_HI-CMW710-R6330.ipe软件包大小为54MB&#xff0c;那么交换机Free的空间需要108M。 空间如果…

H3C 交换机S6520X软件版本升级

1.通过官网下载软件包 升级的包名为 S6520X-CMW710-R6312P02.zip 压缩包里有很多特性包&#xff0c;我们目前就使用 S6520X-CMW710-R6312P02.ipe 2. 查看FLASH空间是否足够 <H3C>dir /all Free的空间需要是软件包的2倍大小&#xff0c;例如S6520X-CMW710-R6312P0…

H3c服务器升级硬盘固件,H3C交换机升级固件版本

二、进入产品支持与服务&#xff0c;找到适配的交换机固件进行下载 三、下载时要求提供用户名密码 用户名&#xff1a;yx800 密码&#xff1a;01230123 四、H3C官方升级说明案例 1.1 实验拓扑(假设SW1上 VLAN 1 的虚地址为10.10.10.1&#xff0c;PC配置同网段地址10.10.10.…

博途V16 更改PLC的型号和固件版本

在线访问&#xff0c;查看硬件PLC的固件版本。 右键&#xff0c;选择更改设备。 选择PLC型号和版本号。

TIA博途_如何更新程序中的指令版本和CPU固件版本?

TIA博途_如何更新程序中的指令版本和CPU固件版本? TIA博途STEP7从V14SP1版本增加新功能:“更新程序”,可以将当前CPU中的程序版本更新至能够使用的最高版本,对于通讯、运动控制等版本经常升级的程序非常适用, 以下进行举例说明: TIA博途STEP7 V13 SP1中组态S7-1200 V4.1版…

TIA PORTAL西门子PLC的CPU固件版本兼容问题

TIA PORTAL西门子PLC的CPU固件版本兼容问题 以S7-1200为例&#xff0c;现在新出的PLC的固件都是V4.4的版本了&#xff0c;而原来的软件如V15.0组态不到V4.4&#xff0c;只能组态到V4.2&#xff0c;在想继续使用V15.0的情况下&#xff0c;这个PLC还可以用吗&#xff1f; 答案是可…

如何在TIA博途中在线更新PLC的CPU固件版本?

如何在TIA博途中在线更新PLC的CPU固件版本? S7-1200PLC最新的V4.6.0版本的固件出来了,本次就以V4.6版本的固件为例,演示如何在博途中对PLC的固件版本进行更新。 (为防止更新过程中出现意外,强烈建议对PLC的程序进行备份!备份!备份!) 如下图所示,打开某个项目,选中PL…

西门子S7-1200如何使用TIA软件更新CPU固件版本

1、先点击上方“可访问的设备”按钮&#xff0c;扫描出当前所连PLC。 2、点击“显示”&#xff0c;在右边目录树中即可显示出所连PLC&#xff0c;点击“在线和诊断”。 3、即可显示出固件版本和上一个使用者所用博图软件版本。 4、打开所连接S7-1200的“在线和诊断”视图&…

软件版本控制流程

1.编写目的 主要针对软件版本的流程, 以确保公司资产得到保护。 2.适用范围 该流程适用于产品研发部门。 3.环境资源 在整个产品生命周期中&#xff0c;以gitlab作为公司主要代码仓库。 4.流程 流程分为版本号定义、版本发布 4.1 版本号定义 4.1.1 版本号规则 采用语义…

康耐视智能相机更新固件版本方式

康耐视智能相机更新固件版本方式 1、 首先下载对应版本的in-sight Explorer软件&#xff0c;软件自带此版本的固件信息 2、 打开软件&#xff0c;将相机与电脑处于同一网段&#xff0c;在系统—将传感器/设备添加到网络 3、 设置好相机的IP 地址 4、 确认相机与电脑在同一网…

keil中查看仿真器固件版本号

1.首先选择仿真器类型 2.然后点击设置&#xff0c;FW Version显示的就是版本号。

如何确定当前的S7-1200PLC使用的具体的博途软件和固件版本?

如何确定当前的S7-1200PLC使用的具体的博途软件和固件版本? 首先,我们要了解,在使用博途软件对S7-1200或1500系列的PLC进行上传或下载等操作时,必须保持软件版本或固件版本的一致性,否则可能会出现意想不到的问题。 那么,如果当前正在使用的PLC或项目程序不是自己做的,…