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为tornado添加recaptcha验证码功能
Feb 26 Python
python对DICOM图像的读取方法详解
Jul 17 Python
利用python实现微信头像加红色数字功能
Mar 26 Python
pycharm使用matplotlib.pyplot不显示图形的解决方法
Oct 28 Python
Python中修改字符串的四种方法
Nov 02 Python
Pytorch 实现自定义参数层的例子
Aug 17 Python
python字符串格式化方式解析
Oct 19 Python
python3实现弹弹球小游戏
Nov 25 Python
Pytorch.nn.conv2d 过程验证方式(单,多通道卷积过程)
Jan 03 Python
Django如何使用redis作为缓存
May 21 Python
python中查看.db文件中表格的名字及表格中的字段操作
Jul 07 Python
Python实现王者荣耀自动刷金币的完整步骤
Jan 22 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控制linux服务器常用功能 关机 重启 开新站点等
2012/09/05 PHP
美图秀秀web开放平台--PHP流式上传和表单上传示例分享
2014/06/22 PHP
利用php抓取蜘蛛爬虫痕迹的示例代码
2016/09/30 PHP
基于JQuery 的消息提示框效果代码
2011/07/31 Javascript
JS代码放在head和body中的区别分析
2011/12/01 Javascript
Windows8下搭建Node.js开发环境教程
2014/09/03 Javascript
Backbone.js 0.9.2 源码注释中文翻译版
2015/06/25 Javascript
jQuery animate()实现背景色渐变效果的处理方法【使用jQuery.color.js插件】
2017/03/15 Javascript
微信小程序实战之自定义toast(6)
2017/04/18 Javascript
NodeJS 实现手机短信验证模块阿里大于功能
2017/06/19 NodeJs
详解vue渲染从后台获取的json数据
2017/07/06 Javascript
在Vue.js中使用Mixins的方法
2017/09/12 Javascript
vue-cli的eslint相关用法
2017/09/29 Javascript
详解如何在nuxt中添加proxyTable代理
2018/08/10 Javascript
js实现自动播放匀速轮播图
2020/02/06 Javascript
JS+HTML5本地存储Localstorage实现注册登录及验证功能示例
2020/02/10 Javascript
[01:23]2014DOTA2国际邀请赛 球迷无处不在Ti现场世界杯受关注
2014/07/10 DOTA
[51:29]完美世界DOTA2联赛循环赛 Matador vs Forest BO2第一场 11.05
2020/11/05 DOTA
python遍历 truple list dictionary的几种方法总结
2016/09/11 Python
python模拟表单提交登录图书馆
2018/04/27 Python
获取python的list中含有重复值的index方法
2018/06/27 Python
python读取文件名并改名字的实例
2019/01/07 Python
python使用opencv对图像mask处理的方法
2019/07/05 Python
python科学计算之narray对象用法
2019/11/25 Python
python 实现方阵的对角线遍历示例
2019/11/29 Python
Python不支持 i ++ 语法的原因解析
2020/07/22 Python
音乐专业应届生教师求职信
2013/11/04 职场文书
公司人力资源的自我评价
2014/01/02 职场文书
长辈证婚人证婚词
2014/01/09 职场文书
运动会广播稿80字
2014/01/23 职场文书
教师个人鉴定材料
2014/02/08 职场文书
运动会广播稿150字
2014/02/19 职场文书
杭白菊导游词
2015/02/10 职场文书
解除劳动合同通知书范本
2015/04/16 职场文书
OpenCV-Python实现人脸美白算法的实例
2021/06/11 Python
Python如何让字典保持有序排列
2022/04/29 Python