Python尾递归优化实现代码及原理详解


Posted in Python onOctober 09, 2020

在传统的递归中,典型的模式是,你执行第一个递归调用,然后接着调用下一个递归来计算结果。这种方式中途你是得不到计算结果,知道所有的递归调用都返回。 这样虽然很大程度上简洁了代码编写,但是让人很难它跟高效联系起来。因为随着递归的深入,之前的一些变量需要分配堆栈来保存。

尾递归相对传统递归,其是一种特例。在尾递归中,先执行某部分的计算,然后开始调用递归,所以你可以得到当前的计算结果,而这个结果也将作为参数传入下一次递归。这也就是说函数调用出现在调用者函数的尾部,因为是尾部,所以其有一个优越于传统递归之处在于无需去保存任何局部变量,从内存消耗上,实现节约特性。
下面以递归计算加法的实例来说明:

我们用python实现:

普通递归调用:

def recursion(n):
  if n==1:
    return n
  else:
    return n+recursion(n-1)

调用这个函数recursion(5),编译器会执行:

recursion(5)
5+recursion(4)
5+(4+recursion(3))
5+(4+(3+recursion(2)))
5+(4+(3+(2+recursion(1))))
5+(4+(3+(2+1)))
15

此处编译器会分配递归栈来保存中间结果

下来看尾递归实现:

def tail_recursion(n,total=0):
  if n==0:
    return total
  else:
    return tail_recursion(n-1, total+n)

此时,编译器做的工作:

tail_recursion(5,0)
tail_recursion(4,5)
tail_recursion(3,9)
tail_recursion(2,12)
tail_recursion(1,14)
tail_recursion(0,15)
15

你可以看到当前时刻的计算值作为第二个参数传入下一个递归,使得系统不再需要保留之前计算结果。

尾递归的优势就显而易见了。

但是python本身不支持尾递归(没有对尾递归做优化),而且对递归的次数有限制,当递归深度超过1000时,会抛出异常:

分别执行recursion(998),tail_recursion(998,0)

输出:

498501
498501

没有问题,当调用

recursion(999),tail_recursion(999,0)时,

输出:RuntimeError: maximum recursion depth exceeded

因为递归次数超出了1000

有人对此为Python的尾递归写了一个优化版本,让Python突破递归调用1000次的限制:Tail Call Optimization Decorator (Python recipe)

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python-基础-入门 简介
Aug 09 Python
Python的ORM框架中SQLAlchemy库的查询操作的教程
Apr 25 Python
Python中函数的参数定义和可变参数用法实例分析
Jun 04 Python
Windows下python3.7安装教程
Jul 31 Python
Python实现的特征提取操作示例
Dec 03 Python
对pandas写入读取h5文件的方法详解
Dec 28 Python
Python实用工具FuckIt.py介绍
Jul 02 Python
Python 转换文本编码实现解析
Aug 27 Python
tensorflow保持每次训练结果一致的简单实现
Feb 17 Python
在keras里面实现计算f1-score的代码
Jun 15 Python
Keras-多输入多输出实例(多任务)
Jun 22 Python
python基于opencv批量生成验证码的示例
Apr 28 Python
Python hashlib模块的使用示例
Oct 09 #Python
浅析Python requests 模块
Oct 09 #Python
Python特殊属性property原理及使用方法解析
Oct 09 #Python
python GUI计算器的实现
Oct 09 #Python
Numpy实现卷积神经网络(CNN)的示例
Oct 09 #Python
Python使用socket_TCP实现小文件下载功能
Oct 09 #Python
python实现逻辑回归的示例
Oct 09 #Python
You might like
php 正则表达式小结
2009/08/31 PHP
php curl选项列表(超详细)
2013/07/01 PHP
destoon整合UCenter图文教程
2014/06/21 PHP
php高清晰度无损图片压缩功能的实现代码
2018/12/09 PHP
Laravel 框架控制器 Controller原理与用法实例分析
2020/04/14 PHP
jQuery读取和设定KindEditor值的方法
2013/11/22 Javascript
jquery、js操作checkbox全选反选
2014/03/12 Javascript
JavaScript设计模式之代理模式介绍
2014/12/28 Javascript
JS生成不重复的随机数组的简单实例
2016/07/10 Javascript
jQuery在ie6下无法设置select选中的解决方法详解
2016/09/20 Javascript
JS实现图文并茂的tab选项卡效果示例【附demo源码下载】
2016/09/21 Javascript
JavaScript  event对象整理及详细介绍
2016/10/10 Javascript
Webpack中css-loader和less-loader的使用教程
2017/04/27 Javascript
详解vue-cli中配置sass
2017/06/21 Javascript
JS实现移动端判断上拉和下滑功能
2017/08/07 Javascript
webpack vue 项目打包生成的文件,资源文件报404问题的修复方法(总结篇)
2018/01/09 Javascript
浅谈ajax在jquery中的请求和servlet中的响应
2018/01/22 jQuery
微信小程序实现城市列表选择
2018/06/05 Javascript
Vue 中axios配置实例详解
2018/07/27 Javascript
Python简单日志处理类分享
2015/02/14 Python
python中列表元素连接方法join用法实例
2015/04/07 Python
Python爬虫之xlml解析库(全面了解)
2017/08/08 Python
windows下Virtualenvwrapper安装教程
2017/12/13 Python
Python之inspect模块实现获取加载模块路径的方法
2018/10/16 Python
对Python的zip函数妙用,旋转矩阵详解
2018/12/13 Python
python之验证码生成(gvcode与captcha)
2019/01/02 Python
python实现差分隐私Laplace机制详解
2019/11/25 Python
python飞机大战pygame游戏框架搭建操作详解
2019/12/17 Python
Python爬虫谷歌Chrome F12抓包过程原理解析
2020/06/04 Python
基于python实现判断字符串是否数字算法
2020/07/10 Python
法国包包和行李箱销售网站:Bagage24.fr
2020/03/24 全球购物
一年级班主任寄语
2014/01/19 职场文书
奥巴马就职演讲稿
2014/05/15 职场文书
优秀团员事迹材料1500字
2014/08/31 职场文书
环保建议书作文300字
2015/09/14 职场文书
win10此电脑打不开怎么办 win10双击此电脑无响应的解决办法
2022/07/23 数码科技