6.4. decorator and 6.4 decorator
Decorator:
Meaning: Add new functions to functions without changing the source code of the original function or calling method of the original function in the entire project
Because the source code of the function cannot be changed, the following results may be returned when the call method is ignored:
def decorator(func): func() print("logging")def test1(): print("test1")def test2(): print("Test2")decorator(test1)decorator(test2)
But this changed the original call method, originally test1 (), and now decorator (test1)
So if we want to keep the call method unchanged, can we make the returned value of the decorator function a function we need and assign it to the original function name?
So:
def timmer1(func): def warpper(): start_time = time.time() func() stop_time=time.time() print("the func run time is %s"%(stop_time-start_time)) return warppertest3=timmer1(test3)
It seems that the above Code does not change the original call method,Call the original test3, which is equivalent to running the warpper in timmer1.
For a function without parameters, the above Code has achieved our goal, but for a function with parameters, the above Code does not input parameters, so you still need to modify
So:
def timmer2(func): def warpper(*args,**kwargs): start_time = time.time() func(*args,**kwargs) stop_time=time.time() print("the func run time is %s"%(stop_time-start_time)) return warpper
In the above Code, because test3 is essentially equal to wrapper, you can directly use test3 (parameter) to input parameters. To solve the problem of uncertain number of parameters, you can use a variable length parameter.
The above code still has a problem and cannot obtain the returned values in the original function. Therefore, we need to add some additional things:
import timedef timmer2(func): def warpper(*args,**kwargs): start_time = time.time() res=func(*args,**kwargs) return res stop_time=time.time() print("the func run time is %s"%(stop_time-start_time)) return warpper
Use a variable to record the return value of the original function.
In this way, we have implemented the basic functions of the decorator.
Supplement:
Python provides the following functions:
@ Decorator name def target decoration function name (): pass # The above effect is: Target decoration function name = decorator (target decoration function name)
So when you need to replace the original function, you can add the @ modifier name to the previous line of the target decoration function definition.
So the above Code will become:
def timmer2(func): def warpper(*args,**kwargs): start_time = time.time() func(*args,**kwargs) stop_time=time.time() print("the func run time is %s"%(stop_time-start_time)) return warpper@timmer2def test7(): print("test7") @timmer2def test6(x): print(x)test7()test6(2)
import timedef timmer2(func): def warpper(*args,**kwargs): start_time = time.time() res=func(*args,**kwargs) return res stop_time=time.time() print("the func run time is %s"%(stop_time-start_time)) return warpper@timmer2def test4(): print("test4 run") return "test4 done"test4()print("--------")print(test4())
The second supplement:
You can use one function and multiple decorators.
For example:
@ Decorator 1
@ Decorator 2