Question 1 Why use decorators?
Expand function functions to reduce redundant code.
Take chestnuts for example. Here is the code:
def add(x,y): return x+y def sub(x,y): return x-y
If you want to output "addition, subtraction, multiplication and division" when each function is executed
The stupid way is to write in each function:
def add(x,y): print('Addition, subtraction, multiplication and division') return x+y def sub(x,y): print('Addition, subtraction, multiplication and division') return x-y
But if there are many functions, the workload is very large
Therefore, if a decorator is used:
def decorator(fun): def wrapper(*args,**kw): print('Addition, subtraction, multiplication and division') return fun(*args,**kw) return wrapper @decorator def add(x,y): return x+y @decorator def sub(x,y): return x-y print(add(1,2))
It can obviously reduce the workload
For the following decorator code, introduce question 2
def decorator(fun): def wrapper(*args,**kw): print('Addition, subtraction, multiplication and division') return fun(*args,**kw) return wrapper
Question 2 How to understand the decorator code? Why return a function? Why do I have to define functions in decorators? Can't you just write one function?
After knowing the function of the decorator, I thought at first that I would just write a function, and then pass the function to be extended as parameters and the parameters required by the extended function into this function
So we have the following test code:
def func(func1,*args,**kw): print('Before execution') func1(*args,**kw) print('After execution') return func @func def func1(): print('123')
You will be surprised to find that I did not call func1, but executed three print s
In fact, this is because @func plus def func1() is equivalent to func1=fun(func1)
If you add a sentence to the code above
func1()
An error will be reported, saying that the parameter is not transferred
The reason for the error is that -----@func + def func1() is equal to func1=fun(func1), so there is func1=func
Therefore, at this time, func1 and func can be regarded as pointing to the same function. Fun needs a function parameter, so if you directly write fun1(), of course, an error will be reported
I think it's well understood by now
Since your goal is to extend the function, there are two prerequisites:
1. add functions to this function without changing the function name and function parameter table
2. the code can only be executed when the function is called
The reasons are as follows:
1. if you only use one function to implement extension, a parameter must be used in the parameter list of this function to pass in the original function. After you assign this function to the original function,
The parameter list of the original function will change, which obviously does not meet the requirement of only extending without changing
2. the above code is executed before the function is called, which is obviously not what we want
Therefore, you must declare another function in the function to implement the extension (because the function declared in python function will not be executed)
Now, if you look at the above code, you can understand:
#The decorator function is a decorative function. You can pass a function and I'll decorate it for you #After finishing decoration, return to the function I decorated def decorator(fun): #The wrapper here is the packaging, or the extension of the original function function. In addition to calling #The original function returns the value processed by the original function (of course, the return value can also change), and increases #New statement def wrapper(*args,**kw): print('Addition, subtraction, multiplication and division') return fun(*args,**kw) return wrapper
It should be clear here
For:
@decorator def add(x,y): return x+y
In fact, it is equivalent to: add=decorator(add)
decorator(add) is equal to wrapper
That is, add=wrapper
If you don't believe it, you can add this code to try:
print(add.__name__)
See if add actually points to the wrapper function
To summarize:
Why return function? Because we want the original function to point to a new function, which extends the function of the original function
Why should I define functions in decorator? Because the functions defined in python functions will not be executed
Can't you just write one function? As above, writing only one function must be executed, and the original function parameters must not be changed
in short
wrapper is the new function with extension function that you actually want
All you have to do is make the old function point to the new function and be compatible with the parameter list of the old function that was called
Well, you'll still ask
Question 3: what if the new function needs other parameters (not those of the original function, but other parameters that need to be passed in)?
Direct upper Code:
def fun(text): def decorator(fun): def wrapper(*args,**kw): print('Addition, subtraction, multiplication and division',text) return fun(*args,**kw) return wrapper return decorator @fun('Fun') def add(x,y): return x+y
You can package another layer of functions on the basis of the original decorator to pass in parameters
At this time, add=fun('fun ') (add)
First call fun to return decorator, then call decorator to return wrapper, then add=wrapper
References:
1.https://www.liaoxuefeng.com/wiki/1016959663602400/1017451662295584
2.https://www.zhihu.com/question/26930016/answer/1047233982