Decorator has been introduced in my previous blog about Python 2.4 features, but that was Tiger, and now I'll take a closer look at its use.
A detailed introduction to decorator in Python 2.4 is already introduced in what's new, so you can take a look.
How to call Decorator
Basically call decorator there are two forms of
The first type:
Copy the Code code as follows:
@A
def f ():
This form is decorator with no parameters. The final Python will be processed as:
Copy the Code code as follows:
f = A (f)
It can also be expanded into:
Copy CodeThe code is as follows:
@A
@B
@c
def f ():
The final Python will be processed as:
Copy the Code code as follows:
f = A (B (C (f)))
Note: The document is written in the form of @a @B @c, but in fact it is not possible to write multiple lines. And the order of execution is in the order of the function call, first the bottom C, then B, then A. Therefore, if decorator has sequential words, it is important to note that the first thing to do is to put it at the bottom, and the last to execute it on top. (there should be no such reverse relationship)
The second type:
Copy the Code code as follows:
@A (args)
def f ():
This form is the notation of the decorator band parameter. Then Python will handle it as:
Copy the Code code as follows:
def f ():
_deco = A (args)
f = _deco (f)
As you can see, Python executes a (args) first to get a decorator function, and then it is processed in the same way as the first.
Definition of the Decorator function
Each decorator should have a corresponding function, which will process the subsequent function, either returning the original function object or returning a new function object. Note that decorator is only used to handle functions and class methods.
The first type:
For the first form of invocation
Copy the Code code as follows:
def A (func):
#处理func
#如func. attr= ' decorated '
return func
@A
def f (args):p
The original function object is still returned after the Func is processed. The parameter of this decorator function is the function to be processed. If you want to return a new function, you can:
Copy the Code code as follows:
def A (func):
def new_func (args):
#做一些额外的工作
return func (args) #调用原函数继续进行处理
Return New_func
@A
def f (args):p
Note that the NEW_FUNC is defined in the same way as the function to be processed, so it can also be written in general, such as:
Copy the Code code as follows:
def A (func):
def new_func (*args, **argkw):
#做一些额外的工作
return func (*args, **argkw) #调用原函数继续进行处理
Return New_func
@A
def f (args):p
As you can see, a new function is defined in a, and a returns the new function. In the new function, some things are handled first, such as checking the parameters, or doing some other work, and then adjusting the original function for processing. This pattern can be thought of, before calling a function, by using the decorator technique, you can do some processing before calling the function. If you want to do some processing after calling the function, or further, after calling the function, some processing based on the return value of the function can be written like this:
Copy the Code code as follows:
def A (func):
def new_func (*args, **argkw):
result = Func (*args, **argkw) #调用原函数继续进行处理
If result:
#做一些额外的工作
Return New_result
Else
return result
Return New_func
@A
def f (args):p
The second type:
For the second form of invocation
In the document, if your decorator uses parameters at the time of invocation, then your decorator function will only use these parameters for invocation, so you need to return a new decorator function, which is consistent with the first form.
Copy the Code code as follows:
def A (ARG):
def _a (func):
def new_func (args):
#做一些额外的工作
return func (args)
Return New_func
Return _a
@A (ARG)
def f (args):p
It can be seen that a (ARG) returns a new decorator _a.
Decorator's application scenario
But I've been thinking, what is the magic of decorator? What are the suitable occasions? Do I need to use it?
The magic of decorator is that it can process the modified function. So this process is done without changing the original function code. It's kind of like I know a little bit about AOP (aspect-oriented programming) ideas.
It fits the occasion I can think of to enumerate out the following:
1. As stated in the documentation, it was originally intended to make it easier to invoke methods such as Staticmethod and Classmethod
2. Before some functions are performed, such as web development, many functions need to check if the user is logged in before calling
3. Do some work after some of this function is executed, such as after the call is complete, write the log according to the return status
4. Do the parameter check
There may be many, you can play the imagination freely
So do I need to use it?
I think it depends on you. However, I think in some cases, the use of decorator can increase the flexibility of the program and reduce the degree of coupling. For example, the previous user login check. It is true that you can write a generic login check function and then make a call in each function. However, this creates a function that is not flexible enough and increases the degree of union with other functions. If the user login check function has been modified, such as the return value of the judgment has changed, it is possible for each function to use it to modify. The use of decorator does not cause this problem. Using the decorator syntax also makes the code simple and clear (but you are familiar with its syntax). Of course it is possible for you not to use it. However, this function of the combination of the way, more in line with the requirements of building blocks, it can be further decomposition function functions, making the function simple enough and single. And then through the mechanism of decorator flexible to string the related functions into a string, such a thought, is really good. such as the following:
Copy the Code code as follows:
@A
@B
def account (args):p
Suppose this is an accounting processing function, the account is billed. But a real accounting also has some judgment and processing, such as: b Check the status of the account, a diary. The effect is to check B first, through the processing in a can first execute the account, and then log processing. As easy as building blocks, it is easy to change them. Even the account can be written as decorator, and the function below is an empty function. Then through the configuration file and other methods, the combination of decorator to save the basic implementation of the function of the Assembly. is not very ideal.
Python's creativity is endless!