In general, similar to Java and C #, Python does not have the ability to automatically optimize tail recursion. recursive calls are widely criticized for being limited by the call stack length, however, this article will give you an incredible method to achieve Python's tail recursion optimization. Therefore, Python's recursive call no longer needs to be restricted by the call stack length.
BKJIA recommended reading: Use Python recursion to process files
Let's take a look at the call method of the last delivery method:
- 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)
To test this program, call 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
If we use Fib (1002), the result is as follows:
- .....
- 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
Now let's optimize the tail recursion. Add a Decorator to the Fib function, as shown below:
- @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)
This is the decorator @ tail_call_optimized. This decorator makes Python magically break the call stack restrictions. Even if we run Fib (20000), we can run the results in ms.
- 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
- functionrecursesinanon-tailcontext.
- """
- 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
The method used has been shown before. The author throws an exception and captures it to break the call stack growth. This is simply incredible. In addition, the efficiency problem is about five times the time overhead compared with direct tail-recursive Fib. Finally, it was incredible that the goal of tail recursion optimization was achieved.
Link: http://www.cnblogs.com/Alexander-Lee/archive/2010/09/16/1827587.html