Python decorator learning and Practical Use Cases

Source: Internet
Author: User
Tags python decorator

Python decorator learning and Practical Use Cases

Preface

I was reading the Flask framework a few days ago. I don't really understand it. I came back to the homework of the decorator. I have read a lot of articles about the decorator. I will sort out the methods and examples that suit my own ideas and share them with you.

 
 
  1. app = Flask(__name__) 
  2. @app.route("/") 
  3. def hello(): 
  4. return "Hello World!" 

1. What is the decorator?

The decorator is an advanced syntax in Python. The main function is to process a function, method, or class. It adds additional functions to existing objects to improve code readability.
The decorator is a design pattern used in scenarios with cut-plane requirements. It is typical for log insertion, performance testing, and transaction processing.

2. decorator syntax

The decorator syntax is as follows:

The current Python decorator syntax is as follows:

 
 
  1. @ Dec2
  2. @ Dec1
  3. Def func (arg1, arg2 ,...):
  4. ....
  5. Return funx
  6.  
  7. The above code is equivalent:
  8.  
  9. Def func (arg1, arg2 ,...):
  10. Pass
  11. Func = dec2 (dec1 (func ))

Decorator can be defined in the format of def.The decorator receives a callable object as the input parameter and returns a new callable object.
The modifier creates a new callable object, that is, the function funx returned by return. In the newly added function, you can add the functions we need, the original function is implemented by calling the original function.

3. Use of decorator

3.1 decorator without Parameters

Defining the decorator is very simple:

 
 
  1. Def deco (func ):
  2. "A parameter is required when a decorator declaration is called without a parameter. This parameter will receive the method to be decorated """
  3. Print "before myfunc () called ."
  4. Func ()
  5. Print "after myfunc () called ."
  6. Return func
  7.  
  8. @ Deco
  9. Def myfunc ():
  10. Print "myfunc) called ."
  11.  
  12.  
  13. Myfunc ()
  14. Myfunc ()

After the decorator is defined, you can use it. The above decorator has a problem when it is used, that is, it is called only for the first time, and the original function is executed once more. The execution output is as follows:

 
 
  1. Before myfunc () called.
  2. Myfunc () called.
  3. After myfunc () called.
  4. Myfunc () called. -- output of multiple function executions once
  5. Myfunc () called. -- the second call, the modifier does not take effect

To ensure that the new function is called every time, use the following method to define the decorator:

 
 
  1. Def deco (func ):
  2. "A parameter is required when a decorator declaration is called without a parameter. This parameter will receive the method to be decorated """
  3. Def _ deco ():
  4. Print "before myfunc () called ."
  5. Func ()
  6. Print "after myfunc () called ."
  7. # Return func does not need to return func
  8. Retrun _ deco
  9. @ Deco
  10. Def myfunc ():
  11. Print "myfunc) called ."
  12. Return 'OK'
  13. Myfunc ()
  14. Myfunc ()

Function output is as follows:

 
 
  1. before myfunc() called. 
  2.  myfunc() called. 
  3.   after myfunc() called. 
  4. before myfunc() called. 
  5.  myfunc() called. 
  6.   after myfunc() called. 

In this way, you can see that the decorator is called every time.

3.2 decorator with Parameters

 
 
  1. def deco(func): 
  2.     def _deco(a, b): 
  3.         print("before myfunc() called.") 
  4.         ret = func(a, b) 
  5.         print("  after myfunc() called. result: %s" % ret) 
  6.     return ret 
  7. return _deco 
  8.  
  9. @deco 
  10. def myfunc(a, b): 
  11.     print(" myfunc(%s,%s) called." % (a, b)) 
  12.     return a + b 
  13.   
  14. myfunc(1, 2) 
  15. myfunc(3, 4) 

Output:

 
 
  1. before myfunc() called. 
  2. myfunc() called. 
  3. After myfunc() called. result: 3 
  4. before myfunc() called. myfunc() called. After myfunc() called. result: 7 

The parameters and return values of nested functions are the same as those of the original function. The decoration function returns the nested packaging function.

3.3 decorator with Parameters

 
 
  1. Def decoWithArgs (arg ):
  2. "Because the decorator function with parameters only uses the parameters in use when calling, rather than receiving the decorated functions as parameters,
  3. Therefore, a decorator function must be returned to encapsulate and process the decorated function """
  4. Def newDeco (func): # define a new decorator Function
  5. Def replaceFunc (): # define an embedded function in the decorator function to encapsulate specific operations.
  6. Print "Enter decorator % s" % arg # perform additional operations
  7. Return func () # Call the decorated Function
  8. Return replaceFunc
  9. Return newDeco # return a new decorator Function
  10.  
  11. @ DecoWithArgs ("demo ")
  12. Def MyFunc (): # decoWithArgs
  13. Print "Enter MyFunc"
  14.  
  15. MyFunc () # Call the decorated Function

Output:
Nter decorator demo
Enter MyFunc

This situation applies to the case where the original function has no parameters and printing is added.A common application is to add function printing logs.

3.4 describe functions with uncertain number of parameters

The following is an example of asynchronous sending of mail. The parameter data of the function is determined. The decorator implements asynchronous sending of the mail sending function.

 
 
  1. from threading import Thread 
  2.  
  3. def async(f): 
  4.     def wrapper(*args, **kwargs): 
  5.         thr = Thread(target = f, args = args, kwargs = kwargs) 
  6.         thr.start() 
  7.     return wrapper 
  8.  
  9. @async 
  10. def send_async_email(msg): 
  11.     mail.send(msg) 
  12.  
  13. def send_email(subject, sender, recipients, text_body, html_body): 
  14.     msg = Message(subject, sender = sender, recipients = recipients) 
  15.     msg.body = text_body 
  16.     msg.html = html_body 
  17.     send_async_email(msg) 

In addition, this decorator can be used for all functions that require asynchronous processing, so as to achieve very good code reuse.

3.5 let the decorator carry Class Parameters

 
 
  1. Class locker:
  2. Def _ init _ (self ):
  3. Print ("locker. _ init _ () shocould be not called .")
  4. @ Staticmethod
  5. Def acquire ():
  6. Print ("locker. acquire () called. This is a static method )")
  7. @ Staticmethod
  8. Def release ():
  9. Print ("locker. release () called. No object instance is required )")
  10. Def deco (cls ):
  11. ''' Cls must implement the acquire and release static methods '''
  12. Def _ deco (func ):
  13. Def _ deco ():
  14. Print ("before % s called [% s]." % (func. _ name __, cls ))
  15. Cls. acquire ()
  16. Try:
  17. Return func ()
  18. Finally:
  19. Cls. release ()
  20. Return _ deco
  21. Return _ deco
  22. @ Deco (locker)
  23. Def myfunc ():
  24. Print ("myfunc () called .")
  25. Myfunc ()
  26. Myfunc ()

Output:

 
 
  1. before myfunc called [__main__.locker]. 
  2. locker.acquire() called.(this is staticmethon) 
  3. myfunc() called. 
  4.   locker.release() called.(do't need object ) 
  5.  
  6. before myfunc called [__main__.locker]. 
  7. locker.acquire() called.(this is staticmethon) 
  8. myfunc() called. 
  9.   locker.release() called.(do't need object ) 

Summary

After applying the decoration method to a method, we actually changed the entry point of the function code block referenced by the decoration function name, point it back to the function entry point returned by the decoration method. Therefore, we can use decorator to change the functions of an original function, add various operations, or completely change the original implementation.

References

Thanks to the following great gods:

Http://www.cnblogs.com/rhcad/archive/2011/12/21/2295507.html

Http://www.cnblogs.com/Jifangliang/archive/2008/07/22/1248313.html

Http://www.cnblogs.com/vamei/archive/2013/02/16/2820212.html

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.