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实现超简单端口转发的方法
Mar 13 Python
Python聚类算法之DBSACN实例分析
Nov 20 Python
python中map()函数的使用方法示例
Sep 29 Python
Python编程深度学习计算库之numpy
Dec 28 Python
Python把对应格式的csv文件转换成字典类型存储脚本的方法
Feb 12 Python
pygame实现俄罗斯方块游戏(AI篇1)
Oct 29 Python
Python计算机视觉里的IOU计算实例
Jan 17 Python
Django高并发负载均衡实现原理详解
Apr 04 Python
Django 如何使用日期时间选择器规范用户的时间输入示例代码详解
May 22 Python
Django之腾讯云短信的实现
Jun 12 Python
python3.7.2 tkinter entry框限定输入数字的操作
May 22 Python
Python Pandas pandas.read_sql_query函数实例用法分析
Jun 21 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
咖啡界又出新概念,无需咖啡豆的分子咖啡
2021/03/03 咖啡文化
header中Content-Disposition的作用与使用方法
2012/06/13 PHP
php中array_fill函数的实例用法
2021/03/02 PHP
javascript事件模型代码
2007/07/01 Javascript
兼容IE与firefox火狐的回车事件(js与jquery)
2010/10/20 Javascript
JS实现随机化快速排序的实例代码
2013/08/01 Javascript
父页面显示遮罩层弹出半透明状态的dialog
2014/03/04 Javascript
jQuery Easyui学习之datagrid 动态添加、移除editor
2016/01/27 Javascript
JavaScript每天必学之基础知识
2016/09/17 Javascript
Bootstrap警告(Alerts)的实现方法
2017/03/22 Javascript
JS实现动态添加DOM节点和事件的方法示例
2017/04/28 Javascript
vue element-ui 绑定@keyup事件无效的解决方法
2018/03/09 Javascript
关于vue-router的那些事儿
2018/05/23 Javascript
vue控制多行文字展开收起的实现示例
2019/10/11 Javascript
vue组件中传值EventBus的使用及注意事项说明
2020/11/16 Javascript
从零学Python之引用和类属性的初步理解
2014/05/15 Python
Windows下安装python2.7及科学计算套装
2015/03/05 Python
在Python中处理XML的教程
2015/04/29 Python
Python利用heapq实现一个优先级队列的方法
2019/02/03 Python
python pandas 时间日期的处理实现
2019/07/30 Python
pip安装python库的方法总结
2019/08/02 Python
Python matplotlib绘制饼状图功能示例
2019/09/10 Python
tensorboard显示空白的解决
2020/02/15 Python
Python字符串格式化f-string多种功能实现
2020/05/07 Python
CSS3 :not()选择器实现最后一行li去除某种css样式
2016/10/19 HTML / CSS
html5默认气泡修改的代码详解
2020/03/13 HTML / CSS
美国最大的电子宠物训练产品制造商:PetSafe
2018/10/12 全球购物
一道SQL存储过程面试题
2016/10/07 面试题
某科技软件测试面试题
2013/05/19 面试题
关于逃课的检讨书
2014/01/23 职场文书
送餐员岗位职责范本
2014/02/21 职场文书
企业厂务公开实施方案
2014/03/26 职场文书
医院信息公开实施方案
2014/05/09 职场文书
《半截蜡烛》教学反思
2016/02/19 职场文书
元素水平垂直居中的方式
2021/03/31 HTML / CSS
mysql sock 文件解析及作用讲解
2022/07/15 MySQL