Search code examples
pythonpython-decorators

python decorating recursive function


I'm trying to use my timer_func decorator to log the process time of fibonacci function. But It seems like the decorator is logging multiple times:

def timer_func(func):
    def inner_func(*args):
        t1 = perf_counter()
        res = func(*args)
        t2 = perf_counter()
        logging.log(logging.INFO, f"Done in {t2 - t1} Seconds!")
        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 of is %d" % (5, r))

Output:

Done in 7.269991328939795e-07 Seconds!
Done in 7.840008038328961e-07 Seconds!
Done in 0.00013806700007990003 Seconds!
Done in 0.0006901449996803422 Seconds!

Solution

  • The log will happen each time the fibonacci function is called. Since the function is recursive, it is getting called multiple times.

    You'll need to make a second version of the function that has the decorator and calls the non-decorated function. For example:

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