An article gives you a complete understanding of python decorators

Keywords: Python

Article catalog

explain

Because I learned from the video, and the content in the video is limited. Basically, I will go to the Internet to find information to deepen and expand it, but the decorator really baffles me. Listen to the video How to use the decorator, how to find information on the Internet, and how to use the decorator, but just because of how to use the decorator, can't I even use it correctly at the beginning?
Whether it's a video or an online blog, when we talk about the decorator, we only talk about what the decorator is and how to use it. However, no one talks about the precautions of the decorator. As a result, people who just touch the decorator will bump into the wall and report various errors. (because the modifier is the same as the def function we usually use, but no one says that the use of the modifier is different from that of the ordinary function, so it is misleading.)
Read a lot of blogs, do a lot of experiments with others' blogs, knock out a lot of code, at first there will be errors, even follow the blog content. Because basically the blog doesn't put the running result chart, there are many duplicate materials to find, and many blog codes are too deep, it's a bit difficult for me who can't even use the decorator correctly.
So I combined with other blogs at the same time, I also summed up the use methods and precautions. I believe that after reading this article, the logic of the decorator can be straightened out.
Last but not least, we should learn the principle first, be familiar with the principle and then expand it. No matter what the grammar is, we should learn the grammar and rules first. When the amount of code is up, the grammar principle is OK, and then we start to move to a higher level. So in the early stage, when we look for information on the Internet, we should learn to filter the grammar actively Don't pay attention to the meaning of the function code in the unreadable code, but to the grammar!

Decorator from the beginning to Understand? Be confident, to be familiar with...

Introduction to decorator

Decorator: the decorator is essentially a function, which is used to handle other functions. It allows other functions to add additional functions without modifying the code (called decorator Decoration, similar to AOP). The return value of the decorator is also a function object. It is often used in scenarios with faceted requirements, such as: insert log, performance test, transaction processing, cache, permission verification and other application scenarios. Decorator is a perfect design to solve this kind of problem. With decorator, we can extract a lot of similar code which has nothing to do with function function itself and continue to reuse it. Generally speaking, the function of decorators is to add additional functions to existing objects.
If the text is a little difficult to understand, let's take a picture to see what the decorator is

The python execution process we understood before is as shown in Figure 1.1
If we add A modifier to the function (as shown in Figure 1.2), when the program executes function A, the system will detect that there is A modifier on function A, and then the system will execute the procedure in the modifier first and then return to the content of the function
Note: the line coming back from the modifier is not necessary. It needs to write back statements in the modifier back to the function. There will be the following statement (called the parameters of the first level function in the two level function).

Simple function of modifier

When we talk about the function of modifiers, let's talk about the requirements first, when can we use them to get modifiers.
For example, I now have a function

def ccx():
    print('my name is ccx')
    print('I want to know  the time')

If I want to know the current time, the normal way is to add functions to the current function, right? So add the time code as follows

import time
def ccx():
    print('my name is ccx')
    print('I want to know  the time')
    print(' | ^ - ^ |' * 5)
    start = time.time()
    start1 = time.asctime(time.localtime(time.time()))
    print('The current timestamp is:', start)
    print('The current time is:', start1)
ccx()


The above is the general method of adding time in a function. But if we have 10 functions, 100 functions need to add this time method??? Copy code and paste it one by one? If so, I'll use python for my short life, which is a contradiction. So there are modifiers.

Define decorator

The function code of the modifier can be customized. You only need to know the syntax and how to define it. How to play the function code of the modifier later.
Syntax:

def name(x):
    def name1():
        # Function code block
        x() #Call parameter. If this parameter is not added, the contents of the function will not be called.
        # Function code block
    return name1()

For example: now define a finisher to realize the printing time!

# Define a time decorator
import time # Time module
def test(func):
    def wrapper():
        start = time.time()
        start1 = time.asctime(time.localtime(time.time()))
        func() # Used to output function contents
        time.sleep(5) #Sleep for 5 seconds
        end = time.time()
        end1 = time.asctime(time.localtime(time.time()))
        print('start Time stamp is:',start)
        print('start The current time is:', start1)
        print('end Time stamp is:',end)
        print('end The current time is:',end1)
    return wrapper()

Note that if you define a decorator alone, there is no output when you run it!!! Because there is no call!

Using decorators

Method: add the @ modifier name to the function using the decorator. python's decorator is a kind of syntax sugar (icing syntax)
For example, now create a ccx() function to call the time display decorator!!!

# Define a time decorator
import time # Time module
def test(func):
    def wrapper():
        start = time.time()
        start1 = time.asctime(time.localtime(time.time()))
        func() # Used to output function contents
        time.sleep(5) #Sleep for 5 seconds
        end = time.time() # time stamp
        end1 = time.asctime(time.localtime(time.time())) # time
        print('start Time stamp is:',start)
        print('start The current time is:', start1)
        print('end Time stamp is:',end)
        print('end The current time is:',end1)
    return wrapper()

@test # Using decorators
def ccx():
    print('my name is ccx')
    print('I want to know  the time')

Note: using the modifier, the function cannot be called, otherwise an error will be reported!!! Because the modifier has its own call, can not be called alone!!! Error reported after calling is as follows!!!

Analyze the execution process, and use the decorator to perform the effect equal to the following figure:

Extended content

Here are some extensions. If you are interested, please take a look at them.

The example given in the second edition of python 3 Program Development Guide (hereinafter referred to as the guide) is a small decorator that is more interesting for python Beginners (no project involved). If you are interested in it, you can have a look at it. I have made some comments on it

def positive_result(function):
    def wrapper(*args, **kwargs):
        # Result get the return value of the function and judge the result
        result = function(*args, **kwargs)
        # assert asserts that if the return value of the function function is greater than or equal to 0, an AssertionError exception will be generated for
        assert result >= 0, function.__name__ + "() result isn't >= 0"
        # return
        return result
   
    # Setting the wrapper's docstring and name to be the same as the original function is conducive to introspection (getting its own information)
    wrapper.__name__ = function.__name__ 
    wrapper.__doc__ = function.__doc__
    return wrapper

# Use positive_result decorator
@positive_result
def discriminant(a,b,c):
    return (b**2) - (4*a*c)


print(discriminant(0,6,5))
print(discriminant(2,6,5))

A simplified version of this example is given in the guide, which uses functools.wraps(function)

def positive_result(function):
    # Wrapper itself uses the function tools module's@ functools.wraps Wrap, which ensures that the name of the wrapper is the same as docstring and function
    @functools.wraps(function)
    def wrapper(*args, **kwargs):
        result = function(*args, **kwargs)
        assert result >= 0, function.__name__ + "() result isn't >= 0"

        return result
    return wrapper
  • Modifier parameterization
    Now we have learned what a decorator is and how to use it. In the above log decorator, our log information is often written to a file, but different functions need to write different file names, so a simple @ decorator name can no longer meet the needs. At this time, we need to parameterize the decorator, Passing the filename to be operated to the test() function
    Now let's take an example from the guide
import functools
def bounded(mininum, maxinum):
    def decorator(function):
        @functools.wraps(function)
        def wrapper(*args, **kwargs):
            result = function(*args, **kwargs)
            if result < mininum:
                return mininum
            elif result > maxinum:
                return maxinum
            return result
        return wrapper
    return decorator

@bounded(0,100)
def percent(amount, total):
    return (amount / total) * 100

percent(15,100)

The implementation process is as follows:

Posted by evilmonkey on Thu, 04 Jun 2020 19:31:48 -0700