Analysis of examples of using decorators in Python programming

WBOY
Release: 2016-07-21 14:53:16
Original
1244 people have browsed it

Decorated functions and methods

We first define two simple mathematical functions, one for calculating the sum of squares and one for calculating the difference of squares:

# get square sum
def square_sum(a, b):
  return a**2 + b**2

# get square diff
def square_diff(a, b):
  return a**2 - b**2

print(square_sum(3, 4))
print(square_diff(3, 4))

Copy after login

After having basic mathematical functions, we may want to add other functions to the function, such as printing input. We can rewrite the function to achieve this:

# modify: print input

# get square sum
def square_sum(a, b):
  print("intput:", a, b)
  return a**2 + b**2

# get square diff
def square_diff(a, b):
  print("input", a, b)
  return a**2 - b**2

print(square_sum(3, 4))
print(square_diff(3, 4))

Copy after login

We have modified the definition of the function and added functions to the function.

Now, we use a decorator to implement the above modifications:

def decorator(F):
  def new_F(a, b):
    print("input", a, b)
    return F(a, b)
  return new_F

# get square sum
@decorator
def square_sum(a, b):
  return a**2 + b**2

# get square diff
@decorator
def square_diff(a, b):
  return a**2 - b**2

print(square_sum(3, 4))
print(square_diff(3, 4))

Copy after login

Decorators can be defined in the form of def, such as decorator in the above code. The decorator receives a callable object as an input parameter and returns a new callable object. The decorator creates a new callable object, which is new_F above. In new_F, we added the printing function and implemented the functions of the original function by calling F(a, b).

After defining the decorator, we can use it through the @ syntax. By calling @decorator before the functions square_sum and square_diff are defined, we actually pass square_sum or square_diff to the decorator, and assign the new callable object returned by the decorator to the original function name (square_sum or square_diff). So, when we call square_sum(3, 4), it is equivalent to:

square_sum = decorator(square_sum)
square_sum(3, 4)
Copy after login

We know that variable names and objects in Python are separated. Variable names can point to any object. In essence, the decorator plays the role of re-pointing to the variable name (name binding), allowing the same variable name to point to a newly returned callable object, thereby achieving the purpose of modifying the callable object.

Similar to processing functions, we can use decorators to process class methods.

If we have other similar functions, we can continue to call decorator to decorate the function without repeatedly modifying the function or adding new packages. In this way, we improve the reusability of the program and increase the readability of the program.

Decorator with parameters

In the above decorator call, such as @decorator, the decorator defaults to the function following it as the only parameter. The syntax of decorators allows us to provide other parameters when calling decorator, such as @decorator(a). This provides greater flexibility in writing and using decorators.

# a new wrapper layer
def pre_str(pre=''):
  # old decorator
  def decorator(F):
    def new_F(a, b):
      print(pre + "input", a, b)
      return F(a, b)
    return new_F
  return decorator

# get square sum
@pre_str('^_^')
def square_sum(a, b):
  return a**2 + b**2

# get square diff
@pre_str('T_T')
def square_diff(a, b):
  return a**2 - b**2

print(square_sum(3, 4))
print(square_diff(3, 4))

Copy after login

The pre_str above is a decorator that allows parameters. It is actually a function encapsulation of the original decorator and returns a decorator. We can understand it as a closure containing environmental parameters. When we call using @pre_str('^_^'), Python can discover this layer of encapsulation and pass the parameters to the decorator environment. This call is equivalent to:

square_sum = pre_str('^_^') (square_sum)

Copy after login

Decoration

In the above example, the decorator receives a function and returns a function, thus achieving the effect of processing the function. After Python 2.6, decorators were extended to classes. A decorator can receive a class and return a class, thus having the effect of processing the class.

def decorator(aClass):
  class newClass:
    def __init__(self, age):
      self.total_display  = 0
      self.wrapped     = aClass(age)
    def display(self):
      self.total_display += 1
      print("total display", self.total_display)
      self.wrapped.display()
  return newClass

@decorator
class Bird:
  def __init__(self, age):
    self.age = age
  def display(self):
    print("My age is",self.age)

eagleLord = Bird(5)
for i in range(3):
  eagleLord.display()

Copy after login

In decorator, we return a new class newClass. In the new class, we record the object (self.wrapped) generated by the original class, and attach a new attribute total_display to record the number of times display is called. We also changed the display method at the same time.

After modification, our Bird class can display the number of times display is called.

Related labels:
source:php.cn
Statement of this Website
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
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
About us Disclaimer Sitemap
php.cn:Public welfare online PHP training,Help PHP learners grow quickly!