The decorator is essentially a Python function. It allows other functions to add additional functions without any code changes. The return value of the decorator is also a function object.
We need a decorator that can test the running time of the function, which can be defined as follows:
def timer(func): def wrapper(*args, **kwargs): start_time = time.time() res = func(*args, **kwargs) end_time = time.time() print("Run time is: %s" % (end_time - start_time)) return res return wrapper
Because it is a decorator, it takes a function as an argument and returns a function. We need to use Python's @ syntax , place the decorator at the definition of the function:
@timer def fun(): time.sleep(1) print("This is a test") return "OK"
The operation result is as follows:
This is a test Run time is: 1.0000572204589844 OK
Put @ timer in fun () is equivalent to executing the statement:
fun = timer(fun)
If the decorator itself needs to pass in parameters, you need to write a higher-order function that returns the decorator, such as adding a name:
def timer(name): def decorator(func): def wrapper(*args, **kwargs): start_time = time.time() res = func(*args, **kwargs) end_time = time.time() print("Name is: %s ; Run time is: %s" % (name, (end_time - start_time))) return res return wrapper return decorator
The call and results are as follows:
@timer("Lance#") def fun(): time.sleep(1) print("This is a test") return "OK"
This is a test Name is: Lance# ; Run time is: 1.0000572204589844 OK
Compared with the two-level nested decorator, the effect of three-level nesting is as follows:
fun = timer("Lance#")(fun)
Because a function is also an object, it also has properties such as name.
Before the decorator is added, the function of fun() calls the property of fun and the result is' fun '. But after decorator is added, the function's name has changed from' fun 'to' wrapper '
Therefore, you need to copy the properties of the original function, such as \.
Python's built-in functools.wraps can accomplish this task. Therefore, a complete decorator can be written as follows:
import functools def timer(func): @functools.wraps(func) def wrapper(*args, **kwargs): start_time = time.time() res = func(*args, **kwargs) end_time = time.time() print("Run time is: %s" % (end_time - start_time)) return res return wrapper
The overall code is as follows:
__Author__ = "Lance#" # -*- coding = utf-8 -*- import time import functools def timer(name): def decorator(func): @functools.wraps(func) def wrapper(*args, **kwargs): start_time = time.time() res = func(*args, **kwargs) end_time = time.time() print("Name is: %s ; Run time is: %s" % (name, (end_time - start_time))) return res return wrapper return decorator @timer("Lance#") def fun(): time.sleep(1) print("This is a test") return "OK" if __name__ == '__main__': print(fun())