python 递归函数_连载|想用Python做自动化测试?递归函数
“ 递归函数就是函数内部调用自身,可以使代码逻辑更加易懂。但是递归也有坑,需要避免。”
13.1 概念
在函数内部,可以调用其他函数。如果一个函数在内部调用自身,这个函数就是递归函数。
理论上,所有的递归函数都可以写成循环的方式,但循环的逻辑不如递归清晰。
计算阶乘n! = 1 x 2 x 3 x ... x n,用函数fact(n)表示:
def fact(n): if n==1: return 1 return n * fact(n - 1)
13.2 写递归代码的套路
写递归代码的关键就是找到如何将大问题分解为小问题的规律,然后按照下面套路即可实现:
第一步,写出递推公式
以计算阶乘为例,递归公式是:fact(n)=n!=n×(n−1)×⋅⋅⋅3×2×1=n×(n−1)!=n×fact(n−1)
第二步,推敲终止条件
以计算阶乘为例,终止条件是n=1时,fact(1)=1。
13.2.1 斐波那契数列
再来看一个斐波那契数列的例子,斐波那契数列中后一个元素是前两个相邻元素的和。比如:
0,1,1,2,3,5,8,13,21,34,55,…。
那么我们如何得到第n个数是多少?分两步走:
第一步,写出递推公式。求第n个元素,可以先求出n-1和n-2个元素的值,然后再将这两个求和,所以公式是:
fibonacci(n) = fibonacci(n - 1) + fibonacci(n - 2)
第二步,推敲最终终止条件。终止条件包含三个:n=0时,f(n)=0;n=1时,f(n)=1;n=2时,f(n)=1。
if n < 1: # 递归终止条件 return 0if n in [1, 2]: # 递归终止条件 return 1
转换成完整代码就是:
def fibonacci(n): if n < 1: # 递归终止条件 return 0 if n in [1, 2]: # 递归终止条件 return 1 return fibonacci(n - 1) + fibonacci(n - 2) # 递归公式
不管是编写递归还是阅读递归代码,只要遇到递归,我们就把它抽象成一个递推公式,不用想一层层的调用关系,不要试图用人脑搞清楚计算机每一步都是怎么执行的。
13.2.2 n 个台阶有多少种走法
再来看看一个例子,假如有 n 个台阶,每次可以跨 1 个台阶或者 2 个台阶,请问走这 n 个台阶有多少种走法?
我们从第一步开始想,如果第一步跨1个台阶,问题就变成了n-1个台架有多少种走法。如果第一步跨2个台阶,问题就变成n-2个台阶有多少种走法。我们把n-1个台阶的走法和n-2个台阶的走法求和,就是n个台阶的走法。用公式表示就是f(n)=f(n-1)+f(n-2)。这就是递归公式了。
再来看看终止条件,最后1个台阶就不需要再继续递归了,只有一种走法,就是f(1)=1。我们把这个放到递归公式里面看下,通过这个终止条件能否求出f(2),发现f(2)=f(1)+f(0),也就是仅知道f(1)是不能求出f(2)的,因此要么知道f(0)的值,或者直接将f(2)作为一个递归终止条件。f(0)表示0个台阶有几种走法,f(2)表示2个台阶有几种走法。明显,f(2)更容易理解一些。所以定为f(2)=2也是一个终止条件,表示最后2个台阶有两种走法,即一次跨1个台阶和一次跨2个台阶。有了f(1)和f(2),就能求出f(3),进而求出f(n)了。
转化成代码即是:
def walk(n): if n == 1: # 递归终止条件 return 1 if n == 2: # 递归终止条件 return 2 return walk(n - 1) + walk(n - 2) # 递归公式
13.3 递归可解决哪类问题
原始问题的解可以分解为几个子问题的解
原始问题和子问题,只有数据规模的不同,求解思路完全一样
存在递归终止条件
13.4 递归存在的问题
堆栈溢出
重复计算
编写递归代码时,我们会遇到很多问题,比较常见的一个就是堆栈溢出,而堆栈溢出会造成系统性崩溃,后果会非常严重。什么是堆栈溢出呢?
函数调用会使用栈来保存临时变量。每调用一个函数,都会将临时变量封装为栈帧压入内存栈,等函数执行完成返回时,再出栈。系统栈或者虚拟机栈空间一般都不大。如果递归求解的数据规模很大,调用层次很深,一直压入栈,就会有堆栈溢出的风险。
可以通过Pycharm工具查看调用栈的情况。在递归公式那行代码上添加断点,不断执行Step Over,可以看到Frames窗口中的栈信息会不断增加和减少,当调用一次函数会增加一帧,当调用返回后会减少一帧。最后返回第一层栈func.py。前面说的堆栈溢出的风险,体现在Frames窗口中的栈帧太多了。
那么,如何避免出现堆栈溢出呢?
通常可以在代码中限制递归调用的最大深度的方式来解决这个问题。比如Python语言,限制了递归深度,当递归深度过高,则会抛出:RecursionError: maximum recursion depth exceeded in comparison异常,防止系统性崩溃。
我们在代码中也可以自己设置递归的深度,比如限制n最大不能超过100,代码如下:
def walk(n): if n == 1: return 1 if n == 2: return 2 if n > 100: raise RecursionError("recursion depth exceede 100") return walk(n - 1) + walk(n - 2)
除此之外,使用递归时还会出现重复计算的问题。什么意思?拿走台阶那个例子来说明。比如计算6个台阶的走法f(6),过程如下图:
从图中,我们可以直观地看到,想要计算 f(5),需要先计算 f(4) 和 f(3),而计算 f(4) 还需要计算 f(3),因此,f(3) 就被计算了很多次,这就是重复计算问题。
那么怎么解决这个问题?为了避免重复计算,我们可以通过字典保存已经求解过的 f(k)。当递归调用到 f(k) 时,先看下是否已经求解过了。如果是,则直接从字典中取值,不需要重复计算,这样就能避免刚讲的问题了。
修改下计算台阶走法的代码,解决重复计算的问题:
data = dict() # 保存中间结果def walk(n): if n == 1: return 1 if n == 2: return 2 if n > 100: raise RecursionError("recursion depth exceed 100") if n in data: # 如果在中间结果中,则直接返回,不用进入递推公式再次计算 return data[n] result = walk(n - 1) + walk(n - 2) # 在递归公式前面增加个查找步骤 data[n] = result # 将计算结果保存在中间结果data字典中 return resultprint(walk(6))
python 递归函数_连载|想用Python做自动化测试?递归函数相关推荐
- c++ 随机字符串_连载|想用Python做自动化测试?了解数值计算和随机数生成神器...
" 本文掌握Python中的几种数值类型,以及算术运算.位运算.数值转换,再学习一个测试中常用来产生随机数的模块." 构建测试知识体系,欢迎关注 Python支持的数值类型有整型i ...
- append函数_连载|想用Python做自动化测试?函数的参数传递机制及变量作用域
" 这一节有点难.看不懂没关系.继续往后学,回头再来看." 10.6 函数参数传递的机制 10.6.1 值传递与引用传递 编程语言的参数传递机制通常有两种: 值传递 拷贝参数的值, ...
- python生活中哪些运用_【想把python运用在实际生活中?那么python查询价格方法可以帮助你】- 环球网校...
[摘要]通过本次课程可以让python学员了解一下python查询价格方法,对代码编程有个感性的认知.也好让大家能够理性选择,不要盲目跟从,选择适合自己当前阶段的学习内容,循序渐进,以兴趣自我探索为向 ...
- 想学python看什么书-想学习Python做数据分析,应该看哪些书?
一.Python编程 /> 本书是一本针对所有层次的Python 读者而作的Python 入门书.全书分两部分:第一部分介绍用Python 编程所必须了解的基本概念,包括matplotlib.N ...
- 3 x 10的python表达式_这道数学题用PYTHON编程语言怎么写? 编程语言python是用
我觉着,这个应该这样解决比较符合计算机解题思路. 下面的回答的,思考的东西太多. # -*- coding: utf-8 -*- __author__ = 'lpe234' __date__ = '2 ...
- pycharm是不是python编程_使用PyCharm进行python开发的简介
使用PyCharm进行python开发的简介 这个是很常见的一个问题,我想学习python,用什么编辑器呢? eclipse+pydev? IDLE? vim? 每个人有自己的习惯,可能是自己琢磨的, ...
- excel和python建模_利用Excel学习Python:准备篇
写在前面 这个系列我们要利用Excel的知识,学会用python进行数据分析,如果你精通Excel想要用python提高数据分析效率,那么这个系列你来对了,如果你已经是python大神,想要建模/算法 ...
- python图像分类_用于实现用python和django编写的图像分类的Keras UI
KerasUI是一种可视化工具,可以在图像分类中轻松训练模型,并允许将模型作为服务使用,只需调用API. https://github.com/zeppaman/KerasUI 主要特点: 用oaut ...
- 计算机导论python知识点_如何系统地自学 Python?
我是自学的Python.从对Python一无所知,到在博客上写Python相关的系列文章(Python快速教程),前后有将近三年的时间.期间有不少门槛,但也充满乐趣.乐趣是自学的最大动力.Python ...
最新文章
- 【java】第二十二节课(HashSet)
- Android中windowTranslucentStatus与windowTranslucentNavigation的一些设置(转)
- Centos中提示You have new mail in /var/spool/mail/root 解决
- HttpClient使用方法(包括POST文件)
- mfc程序转化为qt_智慧虎超:小程序如何为珠宝行业助力?低频商品的高频转化你懂吗...
- docker WARNING: IPv4 forwarding is disabled. 解决方法
- 最新的INTEL FPGA时序分析资料
- PHP从零开始--错误处理函数
- python切割图像,使用Python图像库将一个图像切割成多个图像
- 第六十八期:程序员与医生
- 自动驾驶路径轨迹规划(三阶曲线spline)
- python程序gpu运行时间表_python gpu任务及时调度
- 德勤发布2021中国成长型AI企业研究报告:迈向巅峰之路
- 适合程序员的健身方法(转)
- 浅谈FMA与SMA(test)
- 开关电源入门1-基本原理
- 有关嵌入式、单片机、51单片机、STM32、的一些概念详解
- linux将汇编转为机器码,如何将汇编语言转化为机器码
- 在几何画板中如何制作圆柱的侧面展开动画_如何用几何画板做三棱柱的侧面展开动画...
- 国外名校在线学位申请