Python递归函数的使用及原理是什么
Admin 2022-09-14 群英技术资讯 269 次浏览
如果一个函数,可以自己调用自己,那么这个函数就是一个递归函数。
递归,递就是去,归就是回,递归就是一去一回的过程。
一般来说,递归需要边界条件,整个递归的结构中要有递归前进段和递归返回段。当边界条件不满足,递归前进,反之递归返回。就是说递归函数一定需要有边界条件来控制递归函数的前进和返回。
# 定义一个函数 def recursion(num): print(num) if num == 0: return 'ok' # 这个函数在自己的作用域中调用自己,这个函数就是一个递归函数 recursion(num-1) recursion(10) """ 结果: 10 9 8 7 6 5 4 3 2 1 0 """
我们执行这个函数,参数给了一个10,但是这个函数执行的过程中,又调用了自己,所以现在这个函数就会进入先执行第二次调用自己的过程中,第一次的调用就暂时的阻断了;
第二次调用的时候,num-1,参数就变成了9,继续执行,然后就又执行到了调用自己的代码中,现在就会执行第三次调用的过程中,第二次的调用也阻断了;
这就是 递 的过程;
…………
第十一次调用的时候,num-1,层层的嵌套,参数就变成了0,就符合了作用域中的if num == 0
的条件判断式,第十一次的调用就没有再执行到了调用自己的代码,而是彻彻底底的执行完成了 ,然后代码的执行就又回到了第十次的函数调用中。
第十次的函数调用阻断的时候是执行到了recursion(num-1)
,但是这一行代码执行完了,也就是第十一次调用执行完了,并且后面也没有任何代码,所以第十次调用也结束了,然后就回到了第九次调用;然后第八次;再就是第七次,一直到第一次结束,整个函数的执行就结束了;
这就是 归 的过程。
栈区空间就是我们常说的栈,栈是一个有去有回,先进后出后出的空间,就像我们上面的例子中讲的,我们最先执行的是函数的第一次调用,但是第一次调用却是最后执行释放掉的,而第十一次调用是最后调用,最先执行释放掉的,这就是先进后出。与栈空间概念相违背的是队列空间,队列空间是一个有去有回,先进先出的空间,就像我们平时排队一样,先排队的会比后来的人先买到票,之后我们学习并发的时候,我们会详细的讲述队列的概念。
单独的讲栈堆就是一种数据结构,栈是先进后出的一种数据结构,堆是排序后的一种树状数据结构。
栈区堆区是内存空间,栈区就是按照先进后出的数据结构,无论创建或销毁都是自动为数据分配内存,释放内存,这是系统自动创建的;堆区就是按照排序后的树状数据结构,可优先取出必要的数据,无论创建或者销毁都是手动分配内存,释放内存,这是编程工作者手动编程出来的。
内存空间 | 特点 |
---|---|
内存中的栈区 | 自动分配,自动释放 |
内存中的堆区 | 手动分配,手动释放 |
运行程序时在内存中执行,会因为数据类型的不同而在内存的不同区域运行,因不同语言对内存划分的机制不一,当大体来说,有如下四大区域:
上面的栈区、读取、静态区、代码区都只是内存中的一段空间。
所以我们在使用递归函数的时候要注意,递归函数调用的过程就是一个开辟栈和释放栈的过程,调用的时候开辟栈空间,结束的时候释放栈空间,所以说,如果开辟的空间不结束就会一直存在,就会一直占用内存空间,但是栈空间是一个先进后出的空间,如果新开启的空间不释放掉,之前的空间也不会释放掉的,那么如果我们开辟的空间很多很多,但是又释放不掉,那么我们弱小的内存是否有足够的空间容纳得下这么多的栈呢?如果容纳不下,那么我们的计算机就会爆炸,所以我们在使用递归的时候要注意避免这种情况。尤其是死递归。
每次调用函数时,在内存宗都会单独开辟一个空间,配合函数运行,这个空间叫做栈帧空间。
1、递归是一去一回的过程,调用函数时,会开辟栈帧空间,函数执行结束之后,会释放栈帧空间,递归实际上就是不停地开辟和释放栈帧空间的过程,每次开辟栈帧空间,都是独立的一份,其中的资源不共享。
2、触发回的过程当最后一层栈帧空间全部执行结束的时候,会触底反弹,回到上一层空间的调用处,遇到return,会触底反弹,回到上一层的调用处
3、写递归时,必须给予递归跳出的条件,否则会发生内存溢出,可能会出现死机的情况,所以当递归的层数过多的时候,不建议使用递归。
Python中的环境递归的层数默认为1000层左右,一般都是996层。
# 下面的递归函数没有跳出递归的条件,所以是一个死递归,执行看,是不是1000左右。 def recursion(num): print(num) recursion(num+1) recursion(1)
简单的来说,在函数返回的时候,调用其本身,并且return语句不包含表达式,这样的一个递归函数就是一个尾递归函数。
换句话说返回的东西就是函数本身就是尾递归函数,而递归函数只是自身调用了自身而已。
一般情况下,尾递归的计算在参数中完成。
我们开始的举例是一个尾递归函数吗?不是,因为那个例子这是调用了自己本省,但是并没有返回,所以还是一个普通的递归函数而已。
使用递归的时候,我们通常在一些技术博客上看到一些关于尾递归优化的东西,这是因为尾递归无论调用多少次函数,都只会占用一份空间,只开辟一个栈帧空间,但是目前 cpython 不支持,然而最常见的解释器就是 cpython 。
Python常见的解释器:cpython、pypy、jpython。
尾递归相比普通递归的优点就是返回值不需要额外过多的运算。
阶乘计算
一个正整数的阶乘是所有小于及等于该数的正整数的积,并且0的阶乘为1。
""" 循环计算 """ def factorial(num): if num == 0: return 1 elif num < -1: return '只能是零和正整数' count = 1 for i in range(1, num+1): count *= i return count res = factorial(5) print(res) # 120 """ 使用普通递归 """ def factorial(num): if num == 0: return 1 elif num < -1: return '只能是零和正整数' elif num == 1: return num return num * factorial(num-1) # 普通函数返回的是一个表达式 res = factorial(5) print(res) # 120 """ 使用尾递归 """ def factorial(num, count=1): if num == 0: return 1 elif num < -1: return '只能是零和正整数' elif num == 1: return count return factorial(num-1, count*num) # 尾递归返回的是一个函数,计算式在参数中运算 res = factorial(5) print(res) # 120
斐波那契数列
斐波那契数列是以0、1两个数开头,从这个数列从第3个数开始,每一个数都等于前两树之和。
# 使用循环解决 def fibonacci(num): x, y = 0, 1 if num < 1: return '输入大于0的数字' elif num == 1: return 0 elif num == 2: return 1 for _ in range(num-2): x, y = y, y+x return y res = fibonacci(9) print(res) # 21 """ 使用普通递归 """ def fibonacci(num): if num < 1: return '输入大于0的数字' elif num == 1: return 0 elif num == 2: return 1 return fibonacci(num-1) + fibonacci(num-2) res = fibonacci(9) print(res) # 21 """ 使用尾递归 """ def fibonacci(num, x=0, y=1): if num < 1: return '输入大于0的数字' elif num == 1: return x elif num == 2: return y return fibonacci(num-1, x=y, y=(x+y)) res = fibonacci(9) print(res) # 21
到此,关于“Python递归函数的使用及原理是什么”的学习就结束了,希望能够解决大家的疑惑,另外大家动手实践也很重要,对大家加深理解和学习很有帮助。如果想要学习更多的相关知识,欢迎关注群英网络资讯站,小编每天都会给大家分享实用的文章!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:mmqy2019@163.com进行举报,并提供相关证据,查实之后,将立刻删除涉嫌侵权内容。
猜你喜欢
内容介绍题目描述解题思路/算法分析/问题及解决实验代码运行结果题目描述本次实验为连接数据库的实验,并对数据库进行一些简单的操作,要实现的基本功能如下所示,要能连接并展现数据库里的数据,能够实现插入功能
本文主要介绍python中ord()与chr()的区别:chr()函数参数是0 - 256 的一个整数,ord()函数参数是一个ascii字符;chr()函数返回值是当前整数对应的ascii字符,ord()函数返回对应字符的ascii码;chr函数将ascll码转为字符,ord函数将字符转为ascll码。具体请看下文。
1.reshape2.flatten3.ravel4.stack(1)concatenate(2)vstack(3)dstack(4)hstack(5)r,c模式5.split(1)split(2)vsplit和hsplit6.repeat(1)标量参数(2)列表参数7.tile(1)标量参数(2)元组参数8.sor
python中实现字符串分割的方法有哪些?split() 方法可以实现将一个字符串按照指定的分隔符切分成多个子串,通过该分割操作后,会返回一个列表。
本篇文章给大家带来了关于Python3的相关知识,numpy里有一个非常神奇的函数叫做np.where()函数,下面这篇文章主要给大家介绍了关于Pythonnp.where()的详解以及代码应用的相
成为群英会员,开启智能安全云计算之旅
立即注册Copyright © QY Network Company Ltd. All Rights Reserved. 2003-2020 群英 版权所有
增值电信经营许可证 : B1.B2-20140078 粤ICP备09006778号 域名注册商资质 粤 D3.1-20240008