Home  >  Article  >  Backend Development  >  Python decorator definition and application examples explained

Python decorator definition and application examples explained

乌拉乌拉~
乌拉乌拉~Original
2018-08-22 16:17:371055browse

In the following article, let’s learn about what a python decorator is. Learn about the relevant knowledge about python decorators, as well as the usage of python decorators. Okay, without further ado, let’s get started with the next article.

python decorator

In short, pythonDecorator is a function used to expand the functionality of the original function. This function is special The difference is that its return value is also a function. The advantage of using python decorators is to add new functions to the function without changing the code of the original function.

Since a function is also an object, and function objects can be assigned to variables, the function can also be called through variables.

>>> def now():
...     print('2015-3-25')
...
>>> f = now
>>> f()
2015-3-25

The function object has a __name__ attribute, which can get the name of the function:

>>> now.__name__
'now'
>>> f.__name__
'now'

Now, suppose we want to enhance the function of the now() function, for example, automatically before and after the function call Print logs, but do not want to modify the definition of the now() function. This method of dynamically adding functions while the code is running is called a "Decorator".

Essentially, decorator is a higher-order function that returns a function. Therefore, we need to define a decorator that can print logs, which can be defined as follows:

def log(func):
    def wrapper(*args, **kw):
        print('call %s():' % func.__name__)
        return func(*args, **kw)   
   return wrapper

Observe the above log, because it is a decorator, it accepts a function as a parameter and returns a function. We need to use Python's @ syntax to place the decorator at the definition of the function:

@log
def now():
    print('2015-3-25')

Calling the now() function will not only run the now() function itself, but also print a line before running the now() function Log:

>>> now()
call now():
2015-3-25

Putting @log at the definition of now() function is equivalent to executing the statement:

now = log(now)

Since log() is a decorator and returns a function, so, originally The now() function still exists, but now the now variable with the same name points to the new function, so calling now() will execute the new function, that is, the wrapper() function returned in the log() function.

The parameter definition of the wrapper() function is (*args, **kw). Therefore, the wrapper() function can accept calls with any parameters. Within the wrapper() function, the log is printed first, and then the original function is called.

If the decorator itself needs to pass in parameters, then you need to write a higher-order function that returns the decorator, which will be more complicated to write. For example, to customize the text of the log:

def log(text):
    def decorator(func):
        def wrapper(*args, **kw):
            print('%s %s():' % (text, func.__name__))          
          return func(*args, **kw)  
        return wrapper  
     return decorator

The usage of this 3-layer nested decorator is as follows:

@log('execute')
 def now():
   print('2015-3-25')

The execution result is as follows:

>>> now()
execute now():
2015-3-25

and the two-layer nested decorator Compared with decorator, the effect of 3 levels of nesting is as follows:

>>> now = log('execute')(now)

Let’s analyze the above statement. First execute log('execute'), which returns the decorator function, and then call the returned function and parameters. It is the now function, and the return value is ultimately the wrapper function.

There is no problem with the above two definitions of decorator, but there is still one final step left. Because we said that functions are also objects, they have attributes such as __name__, but if you look at the functions decorated by decorator, their __name__ has changed from the original 'now' to 'wrapper':

>>> now.__name__'
wrapper'

Because the name of the returned wrapper() function is 'wrapper', you need to copy the __name__ and other attributes of the original function to the wrapper() function. Otherwise, some codes that rely on function signatures will execute incorrectly.

There is no need to write code such as wrapper.__name__ = func.__name__. Python’s built-in functools.wraps does this. Therefore, a complete decorator is written as follows:

import functools
   def log(func):
   @functools.wraps(func)
     def wrapper(*args, **kw)
       print('call %s():' % func.__name__)      
     return func(*args, **kw)    
   return wrapper

Or for decorator with parameters:

import functoolsdef log(text):
    def decorator(func):
      @functools.wraps(func)
        def wrapper(*args, **kw):
            print('%s %s():' % (text, func.__name__))        
          return func(*args, **kw)    
         return wrapper  
       return decorator

import functools is to import the functools module. The concept of modules will be explained later. Now, just remember to add @functools.wraps(func) before defining wrapper().

The above is all the content described in this article. This article mainly introduces the knowledge related to python decorator. I hope you can use the information to understand the above content. I hope what I have described in this article will be helpful to you and make it easier for you to learn python.

For more related knowledge, please visit the Python tutorial column on the php Chinese website.

The above is the detailed content of Python decorator definition and application examples explained. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn