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 17 Python
python实时分析日志的一个小脚本分享
May 07 Python
python机器学习实战之最近邻kNN分类器
Dec 20 Python
python 输出上个月的月末日期实例
Apr 11 Python
Python实现图片转字符画的代码实例
Feb 22 Python
解决python 3 urllib 没有 urlencode 属性的问题
Aug 22 Python
python 使用pdfminer3k 读取PDF文档的例子
Aug 27 Python
使用 Python 合并多个格式一致的 Excel 文件(推荐)
Dec 09 Python
TensorFlow2.1.0安装过程中setuptools、wrapt等相关错误指南
Apr 08 Python
Django用户登录与注册系统的实现示例
Jun 03 Python
Python基于数列实现购物车程序过程详解
Jun 09 Python
python实现对doc、txt、xls等文档的读写操作
Apr 02 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
全国FM电台频率大全 - 30 宁夏回族自治区
2020/03/11 无线电
PHP5中虚函数的实现方法分享
2011/04/20 PHP
php中强制下载文件的代码(解决了IE下中文文件名乱码问题)
2011/05/09 PHP
PHP的preg_match匹配字符串长度问题解决方法
2014/05/03 PHP
php常用hash加密函数
2014/11/22 PHP
JS支持带x身份证号码验证函数
2008/08/10 Javascript
jQuery中addClass()方法用法实例
2015/01/05 Javascript
JS实现控制表格行文本对齐的方法
2015/03/30 Javascript
jQuery validate验证插件使用详解
2016/05/11 Javascript
微信js-sdk预览图片接口及从拍照或手机相册中选图接口用法示例
2016/10/13 Javascript
微信小程序 require机制详解及实例代码
2016/12/14 Javascript
node.js操作mysql简单实例
2017/05/25 Javascript
JS实现用特殊符号替换字符串的中间部分区域的实例代码
2018/07/24 Javascript
node微信开发之获取access_token+自定义菜单
2019/03/17 Javascript
VUE异步更新DOM - 用$nextTick解决DOM视图的问题
2020/11/06 Javascript
使用wxpython实现的一个简单图片浏览器实例
2014/07/10 Python
Python运算符重载用法实例分析
2015/06/01 Python
python中实现迭代器(iterator)的方法示例
2017/01/19 Python
Python编程产生非均匀随机数的几种方法代码分享
2017/12/13 Python
python实现SOM算法
2018/02/23 Python
Python3 实现串口两进程同时读写
2019/06/12 Python
pyinstaller参数介绍以及总结详解
2019/07/12 Python
python库matplotlib绘制坐标图
2019/10/18 Python
python自动化测试三部曲之request+django实现接口测试
2020/10/07 Python
pycharm 快速解决python代码冲突的问题
2021/01/15 Python
韩国流行时尚女装网站:Dintchina(中文)
2018/07/19 全球购物
蔻驰西班牙官网:COACH西班牙
2019/01/16 全球购物
25岁生日感言
2014/01/13 职场文书
消防应急演练方案
2014/02/12 职场文书
个人贷款授权委托书样本
2014/10/07 职场文书
2014小学语文教师个人工作总结
2014/12/03 职场文书
婚庆开业庆典主持词
2015/06/30 职场文书
小学英语教师研修感悟
2015/11/18 职场文书
2016开学第一课心得体会
2016/01/23 职场文书
python 实现德洛内三角剖分的操作
2021/04/22 Python
Python+Selenium自动化环境搭建与操作基础详解
2022/03/13 Python