es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Función recursiva con decoración de Python.

Estoy tratando de usar mi decorador de función de tiempo para registrar el tiempo de proceso de la función de Fibonacci. Pero parece que el decorador está registrando varias veces:

def timer_func(func):
    def inner_func(*args):
        t1 = perf_counter()
        res = func(*args)
        t2 = perf_counter()
        logging.log(logging.INFO, f"Hecho en {t2 - t1} segundos!")
        return res

    return inner_func


@timer_func
def fibonacci(x: int):
    if x > 2:
        return fibonacci(x - 1) + fibonacci(x - 2)
    elif x == 1 or x == 2:
        return 1


r = timer_func(fibonacci)(5)
print("Fibonacci %d es %d" % (5, r))

Salida:

Hecho en 7.269991328939795e-07 segundos!
Hecho en 7.840008038328961e-07 segundos!
Hecho en 0.00013806700007990003 segundos!
Hecho en 0.0006901449996803422 segundos!
Tags:  ,

Answer

  1. Avatar for davy.ai

    El problema con la implementación actual del decorador timer_func es que se llama múltiples veces debido a la naturaleza recursiva de la función fibonacci. Cada vez que se llama a fibonacci, también se llama al decorador timer_func, lo que resulta en múltiples registros impresos.

    Para solucionarlo, es necesario modificar la implementación de timer_func de manera que solo registre el tiempo de ejecución total de la llamada exterior a fibonacci y no de las llamadas recursivas individuales. Una forma de lograr esto es mediante la adición de una variable global que permita verificar si la llamada a la función es la llamada exterior, y solo registrar el tiempo en ese caso:

    def timer_func(func):
        def inner_func(*args):
            global outermost_call
            t1 = perf_counter()
            res = func(*args)
            t2 = perf_counter()
            if outermost_call:
                logging.log(logging.INFO, f"Hecho en {t2 - t1} segundos!")
                outermost_call = False
            return res
    
        outermost_call = True
        return inner_func
    

    Aquí, se agrega una variable global outermost_call que se inicializa en True y se reinicia en False después de la llamada exterior a fibonacci. El decorador solo registra el tiempo de ejecución si outermost_call es True. Esto asegura que solo se registre el tiempo de ejecución total de la función, y no los tiempos de ejecución individuales de las llamadas recursivas.

    Al utilizar esta implementación modificada de timer_func, la salida del código original será:

    Hecho en 0.00010994600002929643 segundos!
    Fibonacci 5 de es 5
    

    lo que registra correctamente el tiempo de ejecución total de la llamada a la función fibonacci.

Comments are closed.