轉帖|其它|編輯:郝浩|2010-09-26 11:50:01.000|閱讀 741 次
概述:一般來說,Python和Java、C#一樣,是沒有尾遞歸自動優化的能力的,但本文將給大家介紹如何使用Python來實現尾遞歸優化,希望給大家以啟示。
# 界面/圖表報表/文檔/IDE等千款熱門軟控件火熱銷售中 >>
一般來說,Python和Java、C#一樣,是沒有尾遞歸自動優化的能力的,遞歸調用受到調用棧長度的限制被廣泛的詬病,但本文將給大家一個匪夷所思的方法,來實現Python的尾遞歸優化,因此Python的遞歸調用再也不用受到調用棧長度的制約。
先來看尾遞過方式的調用:
defFib(n,b1=1,b2=1,c=3):
ifn<3:
return1
else:
ifn==c:
returnb1+b2
else:
returnFib(n,b1=b2,b2=b1+b2,cc=c+1)
這段程序我們來測試一下,調用Fib(1001)結果:
>>>defFib(n,b1=1,b2=1,c=3):
...ifn<3:
...return1
...else:
...ifn==c:
...returnb1+b2
...else:
...returnFib(n,b1=b2,b2=b1+b2,cc=c+1)
...
>>>Fib(1001)
703303677114228158218352548771835497701812698363587327426
049050871545371181969335797422494945626117334877504492417
659910881863632654502236471060120533741212738673391111981
39373125598767690091902245245323403501L
如果我們用Fib(1002),結果如下:
.....
File"<stdin>",line8,inFib
File"<stdin>",line8,inFib
File"<stdin>",line8,inFib
File"<stdin>",line8,inFib
File"<stdin>",line8,inFib
File"<stdin>",line8,inFib
RuntimeError:maximumrecursiondepthexceeded
現在我們來尾遞歸優化。我們給剛才的Fib函數增加一個Decorator,如下:
@tail_call_optimized
defFib(n,b1=1,b2=1,c=3):
ifn<3:
return1
else:
ifn==c:
returnb1+b2
else:
returnFib(n,b1=b2,b2=b1+b2,cc=c+1)
就是這個@tail_call_optimized的裝飾器,這個裝飾器使Python神奇的打破了調用棧的限制。這下即使我們Fib(20000),也能在780ms跑出結果。
importsys
classTailRecurseException:
def__init__(self,args,kwargs):
self.args=args
self.kwargs=kwargs
deftail_call_optimized(g):
"""
Thisfunctiondecoratesafunctionwithtailcall
optimization.Itdoesthisbythrowinganexception
ifitisit'sowngrandparent,andcatchingsuch
exceptionstofakethetailcalloptimization.
Thisfunctionfailsifthedecorated
"""
deffunc(*args,**kwargs):
f=sys._getframe()
iff.f_backandf.f_back.f_backandf.f_back.f_back.f_code==f.f_code:
raiseTailRecurseException(args,kwargs)
else:
while1:
try:
returng(*args,**kwargs)
exceptTailRecurseException,e:
args=e.args
kwargs=e.kwargs
func.__doc__=g.__doc__
returnfunc
使用的方法前面已經展示了,作者用了拋出異常然后自己捕獲的方式來打破調用棧的增長,簡直是太匪夷所思了。而且效率問題,和直接尾遞歸Fib相比大概造成了五倍的時間開銷。最后很不可思議的,尾遞歸優化的目的達成了。
本站文章除注明轉載外,均為本站原創或翻譯。歡迎任何形式的轉載,但請務必注明出處、不得修改原文相關鏈接,如果存在內容上的異議請郵件反饋至chenjj@fc6vip.cn
文章轉載自:網絡轉載