I am getting familiar with decorators, and after a couple of tutorials i came up with a decorator that might is useful for me. Is this the proper way to use decorators? Any suggestion about the code?
def timeit_decorator(original_function):
import time
import colorama
def wrapper(*args, **kwargs):
tm = time.time()
res = original_function(*args, **kwargs)
print("Function " + colorama.Fore.GREEN + original_function.__name__ + colorama.Style.RESET_ALL + " executed in " + colorama.Fore.GREEN + "~{:.2f}".format(
(time.time() - tm) / 60) + colorama.Style.RESET_ALL + " minutes!")
return res
return wrapper
Example of usage:
@timeit_decorator
def display(msg):
time.sleep(10)
return msg
print(display(1))
1 Answer 1
When using decorators, you should familiarize yourself with functools.wraps
. Consider the difference in available informations between these two (useless) decorators:
from functools import wraps
def decorate1(func):
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
return wrapper
def decorate2(func):
@wraps(func)
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
return wrapper
When applied to a function:
@decorate1
def test1(x, y, z):
"test1 docstring"
print(x, y, z)
@decorate2
def test2(x, y, z):
"test2 docstring"
print(x, y, z)
The help on each function look quite different:
>>> help(test1)
Help on function wrapper in module __main__:
wrapper(*args, **kwargs)
>>> help(test2)
Help on function test2 in module __main__:
test2(x, y, z)
test2 docstring
Since you’re using Python 3, you should consider using better timing primitives. Namely time.perf_counter()
:
def wrapper(*args, **kwargs):
begin = time.perf_counter()
res = original_function(*args, **kwargs)
elapsed = time.perf_counter() - begin
Lastly, you should consider using format
all along instead of string concatenation:
import time
import colorama
from functools import wraps
def timeit_decorator(original_function):
@wraps(original_function)
def wrapper(*args, **kwargs):
begin = time.perf_counter()
result = original_function(*args, **kwargs)
elapsed = time.perf_counter() - begin
print("Function {color}{}{reset} executed in {color}"
"~{:.2f}{reset} minutes!"
.format(
original_function.__name__,
elapsed / 60,
color=colorama.Fore.GREEN,
reset=colorama.Style.RESET_ALL))
return result
return wrapper
-
\$\begingroup\$ Thanks a lot for the long answer, it was really helpful! \$\endgroup\$Gábor Erdős– Gábor Erdős2016年12月15日 13:02:20 +00:00Commented Dec 15, 2016 at 13:02