一个很Cool的Idear->Python的尾递归优化

一个很Cool的Idear->Python的尾递归优化

偶然在国外一个网站瞅到的,非常的酷,发出来共享一下。一般来说,Python和Java,C#一样是没有尾递归自动优化的能力的,递归调用受到调用栈长度的限制被广泛的诟病,但是这个狂人用一个匪夷所思的方法解决了这个问题并在Python上实现了,从此Python的递归调用再也不用受到调用栈长度的制约,太酷了。

首先我们还是从递归说起,之前我发过一篇 《浅谈递归过程以及递归的优化》其中用到了斐波那契数来作为例子.线性递归的算法由于太过一低效就被我们Pass掉了,我们先来看尾递过方式的调用:

def Fib(n,b1=1,b2=1,c=3):
    if n<3:
        return 1
    else:
        if n==c:
            return b1+b2
        else:
            return Fib(n,b1=b2,b2=b1+b2,c=c+1)</span>

这段程序我们来测试一下,调用 Fib(1001)结果:

>>> def Fib(n,b1=1,b2=1,c=3):

...     if n<3:

...         return 1

...     else:

...         if n==c:

...             return b1+b2

...         else:

...             return Fib(n,b1=b2,b2=b1+b2,c=c+1)

... 

>>> Fib(1001)

70330367711422815821835254877183549770181269836358732742604905087154537118196933579742249494562611733487750449241765991088186363265450223647106012053374121273867339111198139373125598767690091902245245323403501L

>>> 

如果我们用Fib(1002),结果,茶几了,如下:

 

  .....

  File "<stdin>", line 8, in Fib

  File "<stdin>", line 8, in Fib

  File "<stdin>", line 8, in Fib

  File "<stdin>", line 8, in Fib

  File "<stdin>", line 8, in Fib

  File "<stdin>", line 8, in Fib

RuntimeError: maximum recursion depth exceeded

>>> 

 

好了,现在我们来尾递归优化

我们给刚才的Fib函数增加一个Decorator,如下:

@tail_call_optimized

def Fib(n,b1=1,b2=1,c=3):
     if n<3:
        return 1
    else:
        if n==c:
            return b1+b2
        else:
             return Fib(n,b1=b2,b2=b1+b2,c=c+1)

恩,就是这个@tail_call_optimized的装饰器 ,这个装饰器使Python神奇的打破了调用栈的限制。

这下即使我们Fib(20000),也能在780ms跑出结果(780ms是以前博文提到那台2000元的上网本跑出来的结果)

 

不卖关子了,下面我们来看看这段神奇的代码:

import sys  
  
class TailRecurseException:  
  def __init__(self, args, kwargs):  
    self.args = args  
    self.kwargs = kwargs  
  
def tail_call_optimized(g):  
  """  
  This function decorates a function with tail call  
  optimization. It does this by throwing an exception  
  if it is it's own grandparent, and catching such  
  exceptions to fake the tail call optimization.  
    
  This function fails if the decorated  
  function recurses in a non-tail context.  
  """  
  def func(*args, **kwargs):  
    f = sys._getframe()  
    if f.f_back and f.f_back.f_back and f.f_back.f_back.f_code == f.f_code:  
      raise TailRecurseException(args, kwargs)  
    else:  
      while 1:  
        try:  
          return g(*args, **kwargs)  
        except TailRecurseException, e:  
          args = e.args  
          kwargs = e.kwargs  
  func.__doc__ = g.__doc__  
  return func

转载于: http://www.cnblogs.com/Alexander-Lee/archive/2010/09/16/1827587.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值