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.