I am trying to access the time to execute a function that is inside a decorator function.
I followed the direction in this post because I was unable to get the function to take the arguments I passed to it. Now I am unsure of how to get the data from calling the function.
Here is my code:
import time
from functools import wraps
def sort_timer(func):
def outer(func):
@wraps(func)
def inner(*args, **kwargs):
start = time.perf_counter()
func(*args, **kwargs)
finish = time.perf_counter()
return start - finish
return inner
return outer
@sort_timer
def bubble_sort(a_list):
"""Sorts a_list in ascending order"""
for pass_num in range(len(a_list) - 1):
for index in range(len(a_list) - 1 - pass_num):
if a_list[index] > a_list[index + 1]:
temp = a_list[index]
a_list[index] = a_list[index + 1]
a_list[index + 1] = temp
list1 = [60, 19, 22, 14, 43, 27, 3, 77]
x = bubble_sort(list1)
print(x)
It would appear that what is being returned is the inner function. Here is what is logged to the console:
<function sort_timer.<locals>.outer.<locals>.inner at 0x0000027167770310>
Any insight would be appreciated. Thank you.
There appears to be an error in the answer to which you refer. (I'll see about editing and/or commenting on it to fix it.)
It can be fixed by changing return outer
to return outer(func)
. As shown, it's returning the outer function itself; what you want to return is the result of calling that outer function on your original function, which produces the wrapper you actually want.
That said, in your code as shown, you're not really using the double-wrapper technique to any advantage. Unless you plan on supplying additional arguments to the decorator itself (not the decorated function), you could simplify like so:
def sort_timer(func):
@wraps(func)
def inner(*args, **kwargs):
start = time.perf_counter()
func(*args, **kwargs)
finish = time.perf_counter()
return start - finish
return inner
Why not using a simple decorator for timing like eg mentioned in timeit versus timing decorator ?
import time
import functools
def timeit(f):
@functools.wraps(f)
def timed(*args, **kw):
ts = time.time()
result = f(*args, **kw)
te = time.time()
print(f"func:{f.__name__} args:{args}{'' if len(kw) == 0 else kw} took: {(te-ts)*1000 :.3f} msec")
return result
return timed
@timeit
def bubble_sort(a_list):
"""Sorts a_list in ascending order"""
for pass_num in range(len(a_list) - 1):
for index in range(len(a_list) - 1 - pass_num):
if a_list[index] > a_list[index + 1]:
temp = a_list[index]
a_list[index] = a_list[index + 1]
a_list[index + 1] = temp
list1 = [60, 19, 22, 14, 43, 27, 3, 77]
x = bubble_sort(list1)
which prints:
func:bubble_sort args:([3, 14, 19, 22, 27, 43, 60, 77],) took: 0.029 msec
The @functools.wraps(f)
takes f
's meta information and copies it to the decorating function timed
, so that the resulting decorated function keeps the features of the original/target function.
Here is the code for calculating execute time of a function:
import time
def timer(func):
def wrapper(*args, **kwargs):
start = time.time()
func(*args, **kwargs)
end = time.time() - start
print(end)
return wrapper
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.