TRE=Tail Recursion Elimination

创始人是不愿意实现TRE的.他专门用了一篇文章来阐述原因.

http://neopythonic.blogspot.com/2009/04/tail-recursion-elimination.html

1.不利于查BUG.

2.现有的1000递归深度够用.

3.递归不是所有编程的基础,也不是一个日常工具.

4.他举了个例子说明第四点,大概是指Python动态的特性不适合递归:

def f(x):
print 'original'
if x > 0:
return f(x-1)
return 0
g = f
def f(x):
print 'new'
return x
print g(5)

最终结果是4:

original
new
4

最后总结:

After all TRE only addresses recursion that can easily be replaced by a loop.

意思应该是说所有真正需要TRE的地方都能轻松改写为循环.

看来我是不能指望Python语言支持TRE了.

但还是有很多顽强的程序员用各种方法变相支持TRE.比如下面这位还用装饰器的形式实现了.

http://web.mit.edu/kmill/www/programming/tailcall.html

class TailCaller(object) :
def __init__(self, f) :
self.f = f
def __call__(self, *args, **kwargs) :
ret = self.f(*args, **kwargs)
while type(ret) is TailCall :
ret = ret.handle()
return ret class TailCall(object) :
def __init__(self, call, *args, **kwargs) :
self.call = call
self.args = args
self.kwargs = kwargs
def handle(self) :
if type(self.call) is TailCaller :
return self.call.f(*self.args, **self.kwargs)
else :
return self.f(*self.args, **self.kwargs) @TailCaller
def fact(n, r=1) :
if n <= 1 :
return r
else :
return TailCall(fact, n-1, n*r) print fact(2500)

最朴素的形式是:

def TCO(f):
def inner(*nkw,**kw):
result=f(*nkw,**kw)
while callable(result):
result=result()
return result
return inner def fab(n,s=1):
if n<2:
return s
else:
return lambda :fab(n-1,s*n) tcoFab=TCO(fab)
print tcoFab(2500)

这个更容易理解,性能也应该会更好,只是行文略显复杂了一点点.主要是由于Python运行时的动态特性,你不能使用更酷的装饰器形式fab=TCO(fab).

我个人是比较支持这种朴素形式的.

网上还有其他一些什么抛出异常法之类的,用到了sys模块,太复杂了,看不懂,故不用.

Python尾递归-创始人为何不愿TRE以及我们如何模拟TRE的更多相关文章

  1. Python用上锁和解锁 lock lock.acquire lock.release 模拟抢火车票

    Python用上锁和解锁  lock lock.acquire lock.release 模拟抢火车票 import jsonimport timefrom multiprocessing impor ...

  2. 孤荷凌寒自学python第八十五天配置selenium并进行模拟浏览器操作1

    孤荷凌寒自学python第八十五天配置selenium并进行模拟浏览器操作1 (完整学习过程屏幕记录视频地址在文末) 要模拟进行浏览器操作,只用requests是不行的,因此今天了解到有专门的解决方案 ...

  3. Python尾递归优化

    Python开启尾递归优化 cpython本身不支持尾递归优化, 但是一个牛人想出的解决办法:实现一个 tail_call_optimized 装饰器 #!/usr/bin/env python2.4 ...

  4. Python尾递归-求斐波那契数列

    # coding=utf-8 # Fibonacci.py Fib = {} def Fibonacci(n): global Fib if Fib.has_key(n): return Fib[n] ...

  5. Python脚本控制的WebDriver 常用操作 <十二> send_keys模拟按键输入

    下面将使用WebDriver中的send_keys来模拟键盘按键输入 测试用例场景 send_keys方法可以模拟一些组合键操作: ctrl+a ctrl+c ctrl+v 等. 另外有时候我们需要在 ...

  6. Python爬虫入门教程 49-100 Appium安装+操作51JOB_APP(模拟手机操作之一)手机APP爬虫

    爬前准备工作 在开始安装Appium之前,你要先知道Appium是做什么的?Appium 是一个自动化测试开源工具,看到没,做测试用的,它有点类似Selenium,可以自动操作APP实现一系列的操作. ...

  7. Python爬虫学习==>第十二章:使用 Selenium 模拟浏览器抓取淘宝商品美食信息

    学习目的: selenium目前版本已经到了3代目,你想加薪,就跟面试官扯这个,你赢了,工资就到位了,加上一个脚本的应用,结局你懂的 正式步骤 需求背景:抓取淘宝美食 Step1:流程分析 搜索关键字 ...

  8. Python基础(二):斐波那契数列、模拟cp操作、生成8位随机密码

    一.斐波那契数列 目标: 编写fib.py脚本,主要要求如下: 输出具有10个数字的斐波那契数列 使用for循环和range函数完成 改进程序,要求用户输入一个数字,可以生成用户需要长度的斐波那契数列 ...

  9. Python day15装饰器基本理论,以及结合全局变量模拟session

    装饰器(decorator):为其他函数添加附加功能 原则:1.不修改被修饰函数源代码 2.不修改被修饰函数的调用方式 装饰器=高阶函数+函数嵌套+闭包 import time def timmer( ...

随机推荐

  1. 重拾Python(4):Pandas之DataFrame对象的使用

    Pandas有两大数据结构:Series和DataFrame,之前已对Series对象进行了介绍(链接),本文主要对DataFrame对象的常用用法进行总结梳理. 约定: import pandas ...

  2. Python系列之 - 面向对象(2)

    类的三大特性 类的三大特性包括: 封装.继承.多态 一 封装 封装就是将类所用到的所有字段.属性.方法都包含在类代码段里面,当实例调用直接调用类中的方法即可. class People(object) ...

  3. orabbix插件监控oracle表空间问题

    我们安装好orabbix插件后,查看Tablespaces监控项是发项值为none,第一反应是没监控成功,其实不然. 1.我们打开orabbix监控项参数的路径,下面为Tablespaces的sql代 ...

  4. java面试3-对于java中值传递的理解(Hollis)

    这是根据Hollis的直面java内容习得(有兴趣的可以加他微信公众号) 对于初学者来说,要理解java中的值传递很难理解,为什么说java只有值传递?那引用传递呢? java中的错误理解: 错误理解 ...

  5. bzoj 2437: [Noi2011]兔兔与蛋蛋

    Description Solution 考虑犯错误的条件:之前是处于必胜状态,该操作之后就变成了必败状态. 我们可以把这个过程看成两人对网格图进行黑白染色,变成了一个二分图模型,即当前位置向相邻不同 ...

  6. [BZOJ]1064: [Noi2008]假面舞会

    题目大意:n个人,k种假面,每人戴一种,戴第i种的可以看见第i+1种,戴第k种的可以看见第1种,给出m条关系表示一个人可以看到另一个人,问k可能的最大值和最小值.(n<=100,000,m< ...

  7. java的泛型

    泛型概述 先看下面的代码: ArrayList al1 = new ArrayList(); ArrayList al2 = new ArrayList(); al1.add("hello& ...

  8. python中type dtype astype 的用法

    1.type 获取数据类型 2.dtype 数组元素的类型 3.astype 修改数据类型

  9. C# 导入excel报错 :不是预期外部表

    错误原因:由于Excel 97-2003的连接格式与Excel 2010 的 不同造成. 解决方案1: 很多人换了2010后,问的最多的问题之一是2003里最经典的ADO中的“provider=Mic ...

  10. Android开发Java基础之Java语言基础(1)

    Java中的基本数据类型 整数类型 整数类型用来存储整数数值,既没有小数部分的数值.可以是正数,也可以是负数.整数类型在Java程序中有三种表现形式,分别是十进制,八进制,十六进制. 整型数据根据它所 ...