一般来说,Python、Java和C#是没有尾递归优化能力的。
用斐波那契数列举栗子
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)
>>> Fib(1001)
70330367711422815821835254877183549770181269836358732742604905087154537118196933579742249494562611733487750449241765991088186363265450223647106012053374121273867339111198139373125598767690091902245245323403501L
如果我们用1002进行测试,会出现以下结果
>>> Fib(1002)
Traceback (most recent call last):
File "" , line 1, in
File "" , line 8, in Fib
File "" , line 8, in Fib
...
File "" , line 8, in Fib
File "" , line 8, in Fib
File "" , line 8, in Fib
File "" , line 8, in Fib
File "" , line 8, in Fib
File "" , line 8, in Fib
File "" , line 8, in Fib
File "" , line 8, in Fib
File "" , line 8, in Fib
File "" , line 8, in Fib
File "" , line 8, in Fib
File "" , line 8, in Fib
File "" , line 8, in Fib
File "" , 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)
再进行以下1002的测试
>>> factorial(1002)
403595226631845209051880628629640843684504427553075197870696397761049187812849704911861525200847286953691029536005008041199679136947538974195145603806613764659598772448343155346099936257625753094803884027860163939789842138835459726309735765486625072922145181887975022572105212827325352650360822643468087741771243274550281589906300986381710232456423433251607344294784039373634656024124453620089721583696043568454453734050864695625360160060837985907843886863299796154720279007113956951303885722179881815749987309805714978843425686190000118314099658179076045908112174184036411692279009131566184678468723846725908145293854399345046411198447956200779858905167173352465714153538801211087720100276119910066915976203462207958828341534221899791288298092817195947660859191130400508223302612192464542972486137970999130314487401586333890803098965666729069983059073029836289064949751403828279759468153435153751780866336232529843901200433684288385627283533199027396434893357282086051585816529002990308480430936068459723972706109774049015004995093607154690663050562540125426199747069929118955699230774847071199289100876508706102549187041138413686787948205954112870737405031681121042921061995174289468425331650464561340409424173780188880812336110785337046525095105430858497742434742094044183974861014953066385473893642483322068557624990042622887596537142678944093257718557160897828029849892850965669582034472885502604911928460284005306342333130336198553219540604482194933412078382116571387810188247661856673784645931148063936059156551998852938063173052063949026304605205631624638774310744480832995609830297494545245656244455620251778253774769266089821112470989893912601073959708491868875645584730271480394263197569955225062667191096707656654407022887525790856785877899038650115933178051995456774627931040674690671748424144553319969406033752761076645509257674502108335781092379493678262981271954245666983743955528481743109188752583996172412523833843658095508570036882989691250736327439493831143034902758721795187227924667136887444201148357041223132757556636766608468460560883010885098435917684827483525679451551727590758306091652499677082687155106869995981028480229123981226964327190673310250990586533694909587495431670564164338201999882039484224426801780967555634548300999593123533545305689646564984159483631997655252944785081759776787922944000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000L
好吧,这是我从国外的一个网上拉下来的。。。直接贴上
import sys
class TailRecurseException:
def __init__(self, args, kwargs):
self.args = args
self.kwargs = kwargs
def tail_call_optimized(g):
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
使用的方法前面已经展示了,令我感到大开眼界的是,作者用了抛出异常然后自己捕获的方式来打破调用栈的增长,简直是太匪夷所思了。而且效率问题,和直接尾递归Fib相比大概造成了五倍的时间开销。
最后很不可思议的,尾递归优化的目的达成了。
去膜拜作者吧,下面是出处:
http://code.activestate.com/recipes/474088/