Python decorator and python decorator

Source: Internet
Author: User
Tags python decorator

Python decorator and python decorator

The decorator is essentially a Python function that allows other functions to add additional functions without any code changes. The return value of the decorator is also a function object.

It is often used in scenarios with specific requirements, such as log insertion, performance testing, transaction processing, caching, and permission verification. The decorator is an excellent design for solving such problems. With the decorator, we can extract a large number of identical code irrelevant to the function itself and continue to reuse it.

Let's look at a simple example:

  

def now():    print('2017_7_29')

Now there is a new requirement to record the execution log of the function, so add the log code to the Code:

def now():    print('2017_7_29')    logging.warn("running")


Suppose there are multiple similar requirements. How can this problem be solved? Write another logging in the now function? In this way, a large number of identical codes are generated. To reduce repeated code writing, we can redefine a function to process logs and then execute the real business code after the logs are processed.

def use_logging(func):         logging.warn("%s is running" % func.__name__)         func()  def now():         print('2017_7_29')      use_logging(now)

 

It is not difficult to implement it logically. However, every time a function is passed as a parameter to the log function. In addition, this method has destroyed the logic structure of the original code. Before executing the business logic, run now (), but now you have to change it to use_logging (now ). Is there a better way? Of course, the answer is the decorator.

First, you must understand that a function is also an object, and the function object can be assigned to a variable. Therefore, the function can also be called through variables. For example:

 

Def now (): print ('192 _ 7_28 ') f = nowf ()
# The function object has a _ name _ attribute. You can obtain the function name.
Print ('now. _ name __: ', now. _ name __)
Print ('F. _ name __: ', f. _ name __)

 

Simple decorator

In essence, decorator is a high-level 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
# Because log () is a decorator and returns a function, the original now () function still exists,
# The now variable with the same name now 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 be called by any parameter.
# In the wrapper () function, first print the log and then call the original function.

The abovelogBecause it is a decorator, a function is accepted as a parameter and a function is returned. Execute now:

now = log(now)now()
Output result: call now (): 2017_7_28

Function log is the decorator. It wraps the func that executes the real business method in the function and looks like now is decorated by log. In this example, a function is called an Aspect when it enters, which is called Aspect-Oriented Programming ).

Syntax SUGAR:

@logdef now():    print('2017_7_28')

@ Symbol is the syntactic sugar of the decorator. It is used when defining a function to avoid another value assignment operation.

In this way, we can save the now = log (now) sentence and directly call now () to get the desired result. If we have other similar functions, we can continue to call the decorator to modify the function, instead of modifying the function repeatedly or adding new encapsulation. In this way, we have improved the reusability of the program and increased the readability of the program.

The convenience of using the decorator in Python is attributed to the fact that a Python function can be passed as a parameter to other functions like a common object and can be assigned to other variables and can be used as a return value, can be defined in another function.

  Decorator with Parameters:

If the decorator itself needs to input parameters, you need to write a high-order function that returns the decorator, which is a little more complicated to write. For example, to customize the log text:

  

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 three-layer nested decorator usage is as follows:

@log('goal')def now():    print('2017-7-28')
now()

Equivalent

Now = log ('goal') (now)
# First Run log ('execute '), return the decorator function, and then call the returned function. The parameter is the now function. The returned value is the wrapper function.
Now ()

Because the function is also an object, it has__name__But you can see the functions decorated by the decorator.__name__From the original'now'Changed'wrapper':

print(now.__name__)# wrapper

Becausewrapper()The function name is'wrapper'Therefore, the original function's__name__And other attributes are copiedwrapper()Function. Otherwise, code execution that depends on the function signature may fail.

No need to writewrapper.__name__ = func.__name__Such code, Python built-infunctools.wrapsTherefore, a complete decorator statement is as follows:

import functoolsdef log(func):    @functools.wraps(func)    def wrapper(*args, **kw):        print('call %s():' % func.__name__)        return func(*args, **kw)    return wrapper
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

 

 

 

Class decorator:

Let's take a look at the class decorator. Compared with the function decorator, class decorator has advantages such as high flexibility, high cohesion, and encapsulation. You can also use the _ call _ method inside the class to use the class decorator. This method is called when you use the @ method to append the decorator to a function.

  

import timeclass Foo(object):         def __init__(self, func):             self._func = func          def __call__(self):             print ('class decorator runing')             self._func()             print ('class decorator ending')  @Foo def now():         print (time.strftime('%Y-%m-%d',time.localtime(time.time())))      now()

 

 

Summary:

In summary, the purpose of the decorator is to add additional functions to existing objects.

In the object-oriented (OOP) design mode, decorator is called the decoration mode. The decoration mode of OOP needs to be implemented through inheritance and combination. In addition to the decorator that supports OOP, Python directly supports decorator at the syntax level. Python decorator can be implemented using functions or classes.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.