Python implementación optimizada tono de la cola

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)
# 实际使用时注意加停止调用的条件,否则会一直循环调用
Publicado 10 artículos originales · ganado elogios 0 · Vistas 474

Supongo que te gusta

Origin blog.csdn.net/weixin_44549795/article/details/105285710
Recomendado
Clasificación