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中对元组和列表按条件进行排序的方法示例
Nov 10 Python
Python实现解析Bit Torrent种子文件内容的方法
Aug 29 Python
python添加模块搜索路径方法
Sep 11 Python
Python实现PS滤镜中马赛克效果示例
Jan 20 Python
python实现Decorator模式实例代码
Feb 09 Python
tensorflow训练中出现nan问题的解决
Feb 10 Python
实例讲解python中的序列化知识点
Oct 08 Python
对Python中实现两个数的值交换的集中方法详解
Jan 11 Python
Django应用程序入口WSGIHandler源码解析
Aug 05 Python
Matplotlib使用字符串代替变量绘制散点图的方法
Feb 17 Python
Python列表嵌套常见坑点及解决方案
Sep 30 Python
python RSA加密的示例
Dec 09 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+AJAX聊天程序[聊天室]提供下载
2007/07/21 PHP
有关phpmailer的详细介绍及使用方法
2013/01/28 PHP
thinkphp的CURD和查询方式介绍
2013/12/19 PHP
Thinkphp中的volist标签用法简介
2014/06/18 PHP
php数组操作之键名比较与差集、交集赋值的方法
2014/11/10 PHP
Thinkphp自定义代码生成工具及用法说明(附下载地址)
2016/05/27 PHP
Laravel框架实现抢红包功能示例
2019/10/31 PHP
运用Windows XP附带的Msicuu.exe、Msizap.exe来彻底卸载顽固程序
2007/04/21 Javascript
判断js中各种数据的类型方法之typeof与0bject.prototype.toString讲解
2013/11/07 Javascript
node.js中的console.error方法使用说明
2014/12/10 Javascript
jQuery实现模拟marquee标签效果
2015/07/14 Javascript
javascript实现自动填写表单实例简析
2015/12/02 Javascript
Bootstrap教程JS插件弹出框学习笔记分享
2016/05/17 Javascript
详解使用angular-cli发布i18n多国语言Angular应用
2017/05/20 Javascript
Vue项目页面跳转时浏览器窗口上方显示进度条功能
2020/03/26 Javascript
javascript设计模式 ? 迭代器模式原理与用法实例分析
2020/04/17 Javascript
基于JavaScript或jQuery实现网站夜间/高亮模式
2020/05/30 jQuery
JavaScript中的全局属性与方法深入解析
2020/06/14 Javascript
jQuery 移除事件的方法
2020/06/20 jQuery
python基础教程之基本内置数据类型介绍
2014/02/20 Python
python使用PIL模块实现给图片打水印的方法
2015/05/22 Python
python压缩文件夹内所有文件为zip文件的方法
2015/06/20 Python
python读写ini配置文件方法实例分析
2015/06/30 Python
python调用OpenCV实现人脸识别功能
2018/05/25 Python
python matlibplot绘制多条曲线图
2021/02/19 Python
Django ORM 查询管理器源码解析
2019/08/05 Python
哪些是python中web开发框架
2020/06/17 Python
如何在vscode中安装python库的方法步骤
2021/01/06 Python
html5 canvas实现圆形时钟代码分享
2013/12/25 HTML / CSS
创意爱尔兰礼物:Creative Irish Gifts
2020/01/29 全球购物
关于读书的演讲稿800字
2014/08/27 职场文书
2014幼儿园教育教学工作总结
2014/12/17 职场文书
公司环境卫生管理制度
2015/08/05 职场文书
青年岗位能手事迹材料(2016推荐版)
2016/03/01 职场文书
mysql数据插入覆盖和时间戳的问题及解决
2022/03/25 MySQL
Python+Selenium实现抖音、快手、B站、小红书、微视、百度好看视频、西瓜视频、微信视频号、搜狐视频、一点号、大风号、趣头条等短视频自动发布
2022/04/13 Python