python函数递归调用的实现
作者:程序员 发布时间:2022-08-14 20:03:57
引入
函数既可以嵌套定义也可以嵌套调用。嵌套定义指的是在定义一个函数时在该函数内部定义另一个函数;嵌套调用指的是在调用一个函数的过程中函数内部有调用另一个函数。而函数的递归调用指的是在调用一个函数的过程中又直接或者间接的调用该函数本身。
函数递归介绍
函数递归就是函数的递归调用,是函数嵌套调用的一种特殊形式,具体就是指在调用一个函数的过程中直接或者间接的调用到本身,递归的本质就是循环做重复的事情。
在调用func的过程中又调用func,这就是直接调用函数本身;
在调用func的过程中调用foo,而在调用foo的过程中又调用func,这就是间接调用func本身。
通过上面的分析,两种情况下的函数递归调用都是一个无限循环的过程,Python为了防止函数递归进入无限循环对函数递归调用的深度做了限制,一旦超出限制就会抛出异常。
def foo():
print('foo')
func()
def func():
print('func')
foo()
func()
'''
程序运行结果:
RecursionError: maximum recursion depth exceeded while calling a Python object(超过最大递归深度)
'''
因此为了避免函数递归调用报错,就必须在满足某中条件的情况下结束对函数的递归调用。
def foo(n):
if n == 1:
print('递归结束')
return
else:
foo(n-1)
foo(2)
函数递归原理及使用
通过一个简单的小学数学题说明递归的原理及使用。
小一比小二多一个苹果,小二比小三多一个苹果,小三比小四多一个苹果,小四有两个苹果,问小一有几个苹果?
这个题目非常简单,解答思路如下:
要想知道小一的苹果数量就需要知道小二的苹果数量,而小二的苹果数量又取决于小三,小三的苹果数量又是基于小四的苹果数量:
app_num(1) = app_num(2) + 1
app_num(2) = app_num(3) + 1
app_num(3) = app_num(4) + 1
app_num(4) = 2
因此可以总结出下面的结论:
app_num(4) = 2
app_num(x) = app_num(x+1) + 1
很明显是一个重复调用同一种方法的过程,只是参数不同,也就是一个递归的过程,通过上面的分析可以将递归过程分为两个阶段 - 回溯和递推。
回溯阶段:想要计算小一(x=1)的苹果数量就需要回溯得到小二(x+1)的苹果,以此类推,直到得到小四的苹果个数,此时app_num(4)已知,就无需再向前回溯。
递推阶段:从小四的苹果数量可以推算出小三的苹果数量,从小三的苹果数量可以推算出小二的,以此类推,一直推算出小一的苹果数量为止,递归结束。需要注意的是,递归一定要有结束条件,这里当x=1就是结束条件。
递归的本质就是在做重复的事情,理论上说递归可以解决的问题循环也都可以解决,只不过是在某种情况下使用递归更容易实现。
def apple_num(x):
if x == 4: # 结束递归的条件
return 2
return apple_num(x+1) + 1
apple_num1 = apple_num(1)
print(apple_num1) # 5
Practice
一个嵌套多层的列表要求打印出所有的元素。
list1 = [[[1, 2], [3, 4], [5, [6, 7], [8, 9, 10], 11, 12], 13]]
def func(items):
for elements in items:
if type(elements) is list:
func(elements)
else:
print(elements)
func(list1)
有一个按照从小到大顺序排列的数字列表,需要从该数字列表中找到我们想要的数字,如何更高效?
# 使用二分法:先取出列表的中间位置的值,与需要的数字进行比较,如果中间位置的值大于需要的值,那么就在中间值的左侧2 进行比较,如果小于,那么就在中间值的右侧进行比较,如果刚好等于,就输出值。然后对上述步骤进行循环
list1 = [0,2,5,7,9,11,34]
find_num = 2
def func(find_num,list1):
# 输出每次切分后生成的list1
print(list1)
mid_index = len(list1) // 2
if find_num > list1[mid_index]:
list1 = list1[mid_index+1:]
func(find_num,list1)
elif find_num < list1[mid_index]:
list1 = list1[:mid_index]
func(find_num,list1)
elif find_num == list1[mid_index]:
print(f'找到了{list1[mid_index]},索引为{mid_index}')
elif len(list1) == 0:
print('不存在这个值')
return
func(find_num,list1)
来源:https://blog.csdn.net/nhb687096/article/details/130495646


猜你喜欢
- MAC下MYSQL5.7.17无法连接的问题,下载安装完SQLBench_community 6.3.9后新建MYSQL CONNECTIO
- 小编最经常的工作是将一些项目的数据从数据库导出,然后分门别类的列到excel表格中,领导看起来眼花缭乱。小编想,要是能以图表可视化展现出来,
- BigPipe 是 Facebook 开发的优化网页加载速度的技术。网上几乎没有用 node.js 实现的文章,实际上,不止于 node.j
- 英文文档:format(value[, format_spec])Convert a value to a “formatted” repr
- 一共4个页面:form.asp; chk.asp; num.asp; count.asp得到一个随即数字。加密
- 问题今天用nohup后台执行python程序,并将标准输出和错误输出重定向到一个log文件,但发现log文件隔好久才会更新,很煎熬。。。然而
- 导出单个表mysqldump -u user -p dbname tablename > db.sql导入单个表mysql>dr
- replace方法的语法是:stringObj.replace(rgExp, replaceText) 其中stringObj是字符串(st
- 要访问一个MySQL服务器,你需要使用一个用户帐号登录其中方可进行。每个MySQL用户帐号都有许多与之相关连的属性,例如用户名、密码以及权限
- window.close(); 关闭浏览器窗口js代码的总结介绍序号关闭代码需要确认无任何作用无需确认测试1window.close()IE
- 问题Go语言在编译时不会将配置文件这类第三方文件打包进二进制文件中它既受当前路径的影响,也会因所填写的不同而改变,并非是绝对可靠的解决命令行
- 给定一个可迭代sequence,对其中的值进行出现次数统计:方法1:def get_counts(sequence): counts = {
- SQL Server 2000 清理日志精品教程SQL Server 2000 数据库日志太大!如何清理SQL Server 2000的日志
- 最近开发的微信公众号项目中(项目采用Vue + Vux 构建,站点部署在IIS8.5上),遇到个非常奇葩的问题,发布站点内容后,通过微信打开
- 一、什么是函数装饰器1.函数装饰器是Python提供的一种增强函数功能的标记函数;2.装饰器是可调用的函数对象,其参数是另一个函数(被装饰的
- Python列表具有内置的 list.sort()方法,可以在原地修改列表。 还有一个 sorted()内置的函数从迭代构建一个新的排序列表
- 如下所示:<!doctype html><html lang="en"> <head>
- 一.前言众所周知:没有对象怎么办?那就new一个!那么在JS中,当我们new一个对象的时候,这个new关键字内部都干了什么呢?现在我们就来剖
- 多表连接的基本语法多表连接,就是将几张表拼接为一张表,然后进行查询select 字段1, 字段2, ...from 表1 {inner|li
- 1 概述1.1 贪心算法贪心算法总是作出在当前看来最好的选择。也就是说贪心算法并不从整体最优考虑,它所作出的选择只是在某种意义上的局部最优选