Python decorator usage example summary, python decorator usage example

Source: Internet
Author: User
Tags python decorator

Python decorator usage example summary, python decorator usage example

This document describes how to use the Python decorator. We will share this with you for your reference. The details are as follows:

I. What is the decorator?

The python 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. In short, the decorator is a function used to return functions.

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.

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

Ii. Why do you need a decorator?

1. Let's look at a simple example:

def foo():print('i am foo')

2. Increase demand

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

def foo():  print('i am foo')  print("foo is running")

3. There are demands

Suppose there are now 100 functions that need to be added, and the need to print logs before executing these one hundred functions may be added in the future. What should I do? Are there any other changes?

Of course not, this will lead to a lot of identical code. To reduce repeated code writing, we can do this and redefine a function: Specially processing logs, after the logs are processed, execute the real business code.

def use_logging(func):  print("%s is running" % func.__name__)  func()def bar():  print('i am bar')use_logging(bar)#result:#bar is running#i am bar

With the preceding use_logging function, we have added the log function. No matter how many functions need to add logs or modify the log format, we only need to modify the use_logging function and execute use_logging (decorated function) it achieves the desired effect.

def use_logging(func):  print("%s is running" % func.__name__)  return func@use_loggingdef bar():  print('i am bar')bar()

3. Basic decorators

1. decorator syntax sugar

Python provides @ symbol as the syntactic sugar of the decorator, which makes it easier for us to use decorative functions. However, syntax sugar requires that the decoration function must return a function object. Therefore, we wrap the above func functions with nested functions and return.

The decorator executes the decoration function use_loggin and returns the decorated function bar. Therefore, when bar () is called, two functions are executed. Equivalent to use_logging (bar )()

def use_logging(func):  def _deco():    print("%s is running" % func.__name__)    func()  return _deco@use_loggingdef bar():  print('i am bar')bar()

2. Decoration of functions with Parameters

Now our parameters need to be passed in two parameters and calculated values, so we need to modify the inner function and pass in our two parameters a and B, which is equivalent to use_logging (bar) (1, 2)

def use_logging(func):  def _deco(a,b):    print("%s is running" % func.__name__)    func(a,b)  return _deco@use_loggingdef bar(a,b):  print('i am bar:%s'%(a+b))bar(1,2)

The number and type of parameters of the decoration function are different. Do we need to modify the decoration device every time? This is of course not scientific, so we use python's variable length parameters * args and ** kwargs to solve our parameter problems.

3. The number of function parameters is unknown.

The decorator version without parameters. This format is applicable to decorator without parameters.

After the following modifications, we have adapted parameters of various lengths and types. The decorator of this version can have any type of non-parameter functions.

def use_logging(func):  def _deco(*args,**kwargs):    print("%s is running" % func.__name__)    func(*args,**kwargs)  return _deco@use_loggingdef bar(a,b):  print('i am bar:%s'%(a+b))@use_loggingdef foo(a,b,c):  print('i am bar:%s'%(a+b+c))bar(1,2)foo(1,2,3)

4. decorator with Parameters

Parameter-based decorators. This format is applicable to parameter-based decorators.

In some cases, we need to add parameters to the decorator, so we need to write a high-order function that returns a decorator, which is more complicated to write. For example:

#! /Usr/bin/env python #-*-coding: UTF-8-*-# _ author _ = "TKQ" def use_logging (level): def _ deco (func ): def _ deco (* args, ** kwargs): if level = "warn": print "% s is running" % func. _ name _ return func (* args, ** kwargs) return _ deco @ use_logging (level = "warn") def bar (a, B ): print ('I am bar: % s' % (a + B) bar (1, 3) # equivalent to use_logging (level = "warn") (bar) (1, 3)

5. functools. wraps

The code is greatly reused with the decorator, but one drawback is that the metadata of the original function is missing, such as docstring, _ name _, and parameter list of the function. Let's look at the example first:

Def use_logging (func): def _ deco (* args, ** kwargs): print ("% s is running" % func. _ name _) func (* args, ** kwargs) return _ deco @ use_loggingdef bar (): print ('I am bar') print (bar. _ name _) bar () # bar is running # I am bar # _ deco # The function name is changed to _ deco instead of bar, this may cause problems when using the reflection feature. Therefore, functools. wraps is introduced to solve this problem.

Use functools. wraps:

Import functoolsdef use_logging (func): @ functools. wraps (func) def _ deco (* args, ** kwargs): print ("% s is running" % func. _ name _) func (* args, ** kwargs) return _ deco @ use_loggingdef bar (): print ('I am bar') print (bar. _ name _) bar () # result: # bar is running # I am bar # bar. This result is what we want. OK!

6. implement self-adaptation of decorator with or without Parameters

Import functoolsdef use_logging (arg): if callable (arg): # judge whether the input parameter is a function. The decorator without parameters calls this branch @ functools. wraps (arg) def _ deco (* args, ** kwargs): print ("% s is running" % arg. _ name _) arg (* args, ** kwargs) return _ deco else: # Call this branch def _ deco (func): @ functools. wraps (func) def _ deco (* args, ** kwargs): if arg = "warn": print "warn % s is running" % func. _ name _ return func (* args, ** kwargs) return _ deco @ use_logging ("warn") # @ use_loggingdef bar (): print ('I am bar') print (bar. _ name _) bar ()

Iii. Class decorator

The class decorator can be used to achieve the effect of the parameter decorator, but the implementation is more elegant and concise, and can be flexibly expanded through inheritance.

1. Class decorator

Class loging (object): def _ init _ (self, level = "warn"): self. level = level def _ call _ (self, func): @ functools. wraps (func) def _ deco (* args, ** kwargs): if self. level = "warn": self. every y (func) return func (* args, ** kwargs) return _ deco def every Y (self, func): # logit only logs are typed, no other print "% s is running" % func. _ name __@ loging (level = "warn") # Run the _ call _ method def bar (a, B): print ('I am bar: % s' % (a + B) bar (1, 3)

2. inherit the extended class decorator

Class email_loging (Loging): ''' an implementation version of loging. You can send an email to the Administrator ''' def _ init _ (self, email = 'admin @ myproject.com ', * args, ** kwargs): self. email = email super (email_loging, self ). _ init _ (* args, ** kwargs) def notify y (self, func): # send an email to self. email print "% s is running" % func. _ name _ print "sending email to % s" % self. email @ email_loging (level = "warn") def bar (a, B): print ('I am bar: % s' % (a + B) bar (1, 3)

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.