Python implementación optimizada tono de la cola
Use 'en Python retorno nombre de la función + ()' se puede lograr llamada de cola, es decir, inmediatamente después del final de la función actual de una llamada de función.
Pero Python sólo puede tailwater 1000, superará el error.
El siguiente es un ejemplo de un tono de cola convencional:
def a(e):
print('%s'%e)
return a(e + 1)
a(1)
resultados:
1
2
3
...
995
996
RecursionError: maximum recursion depth exceeded while calling a Python object
El error será en la profundidad del agua de descarga de más de 1.000 más tarde, no más lejos aguas abajo.
Una vaca se le ocurrió una solución
El siguiente código define un decorador (por python3 +)
# 低版本Python改成 class TailRecurseException:
class TailRecurseException(BaseException):
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()
# 为什么是grandparent, 函数默认的第一层递归是父调用,
# 对于尾递归, 不希望产生新的函数调用(即:祖父调用),
# 所以这里抛出异常, 拿到参数, 退出被修饰函数的递归调用栈!
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)
# 低版本Python改成 except TailRecurseException, e:
except TailRecurseException as e:
# 捕获异常, 拿到参数, 退出被修饰函数的递归调用栈
args = e.args
kwargs = e.kwargs
func.__doc__ = g.__doc__
return func
El ejemplo anterior es el siguiente a continuación de la siguiente manera:
@tail_call_optimized
def a(e):
print('%s'%e)
return a(e + 1)
a(1)
# 实际使用时注意加停止调用的条件,否则会一直循环调用