0 Preface
>>Return to Python series article directory<<
1 callback function
In any language, there are hierarchical relationships between modules, such as:
up_file is the upper module, low_file is a lower level module
# Upper up_file from low_file import * def up_function(): # code
# Lower level low_file def low_function(): # code
Up in the upper module_ Use lower level module low in file_ File function low_function() is very simple. Just call it directly as a local function. But if you want to lower the module low_ Use the upper module up in file_ File function up_function(), a callback is required:
Callback process:
1. Low in lower module_ File defines a function, and the input parameter must be a function
# Lower level low_file def low_call(func): func()
2. Up in the upper module_ File calls this function and puts its own function as an input parameter. Be careful not to add parentheses
# Upper up_file from A_file import * def B_callback(): # code if __name__ == "__main__" A_call(B_callback)
This is passed into the lower function B_callback() is the callback function
2 trimmer
2.1 decorator without parameters
Using the callback function, Python designed a special function called decorator decorator
- First, define a decorator function decorator, and the input parameter is a callback function
- Define a template function wrapper in the decorator function. The input parameters are * args and * * kwargs, indicating that any form of input parameters are accepted
- Callback function func(*args, **kwargs) is invoked in the wrapper(*args, **kwargs) function.
- Perform the actions you want to attach, such as timing, up and down the callback function
- Decorator function decorator returns the defined wrapper function
import time def decorator(func): def wrapper(*args, **kwargs): startTime = time.time() ret = func(*args, **kwargs) # Callback function endTime = time.time() msecs = (endTime - startTime)*1000 print("time is %d ms" %msecs) return ret return wrapper
This decorator function can be added to the last line of any function definition in the form of @ decorator, and the modified function will automatically become the callback function of the decorator function during execution
@decorator def func1(a,b): # code @decorator def func2(a,b,c): # code if __name__ == '__main__': ret = func1(a,b) ret = func2(a,b,c)
Explain the process:
- Call a function with decorator, and perform the following syntax conversion:
- Before conversion
@decorator def func1(a,b): # code func1(a,b)
- After conversion
decorator(func1)(a, b)
- The result of decorator(func1) is return wrapper, so it is converted to:
wrapper(a, b)
- So the wrapper(a, b) function is actually executed
def wrapper(a, b): startTime = time.time() ret = func1(a, b) # Callback function endTime = time.time() msecs = (endTime - startTime)*1000 print("time is %d ms" %msecs) return ret
2.2 decorator with parameters
The decorator with parameters is defined as follows, and a layer of encapsulation middle is added:
def decorator(deco_args): def middle(func): def wrapper(*args,**kwargs): print(deco_args) ret=func(*args,**kwargs) return ret return wrapper return middle
The process is as follows:
- Call a function with decorator, and perform the following syntax conversion:
- Before conversion
@decorator(deco_args) def func1(a,b): # code func1(a,b)
- After conversion
decorator(deco_args)(func1)(a, b)
- The result of decorator(deco_args) is return middle, so it is converted to:
middle(func1)(a, b)
- The result of middle(func1) execution is return wrapper, so it is converted to:
wrapper(a, b)
- Finally, the wrapper(a, b) function is actually executed and the parameter Deco is brought in_ args
def wrapper(a, b): print(deco_args) ret = func1(a, b) # Callback function return ret
2.3 preserve the properties of the original function
There is a problem when the decorator runs. During debug, the decorated function func1__ name__ Disappeared, leaving only the wrapper function in the debug message. If you want to preserve the properties of the original function, you can use functools Wraps
functools.wraps can copy the specified attributes of the original function object to the wrapper function object. By default, there are module, name and doc. The code is as follows:
from functools import wraps def decorator(deco_args): def middle(func): @wraps(func) def wrapper(*args,**kwargs): print(deco_args) ret=func(*args,**kwargs) return ret return wrapper return middle