Home > front end >  Decorators for recursion function
Decorators for recursion function

Time:03-19

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)

CodePudding user response:

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.

  • Related