'Decorators for recursion function

I want to write a decorator that will compute runtime of function that compute fibonachi number of 5(fib(5)) 10 times and will print a medium runtime value. But my decorator returns an error. How to fix this problem?

import functools
import time

def trace(times):
    def cache(func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            total = 0
            for i in range(times):
                start = time.time()
                func(*args, **kwargs)
                end = time.time()
                total += (end - start)
            print('Medium value is {}'.format(total / times))
            return func
        return wrapper
    return cache

@trace(times=10)
def fib(num):
    if num < 2:
        return num
    return fib(num - 1) + fib(num - 2)

fib(5)


Solution 1:[1]

First, instead of returning func in the wrapper return the result of it.

We have to make sure the tracing only happens for the first call to fib and none of the recursive calls. Let's use a boolean traced argument:

import functools
import time

def trace(times):
    def cache(func):
        @functools.wraps(func)
        def wrapper(*args, traced=True, **kwargs):
            if not traced:
                return func(*args, **kwargs)
            total = 0
            for i in range(times):
                start = time.time()
                result = func(*args, **kwargs)
                end = time.time()
                total += (end - start)
                print(f'run {i}, time is {total}')
            print(f'Mean value is {total / times}')
            return result
        return wrapper
    return cache


@trace(times=10)
def fib(num, traced=True):
    if num < 2:
        return num
    return fib(num - 1, traced=False) + fib(num - 2, traced=False)


fib(5)

traced is True by default so any call to fib(n) will be traced (no need for user to be aware of the traced argument). However the recursive calls all have traced=False therefore they don't trigger the loop in the decorator.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1