Python decorator points supplement

  • 2020-10-07 18:46:19
  • OfStack

First, review 1 about the Python decorator and the decorator pattern

completion

According to Java to implement the decorator pattern, we can write the following code:


import logging


def use_logging(func):
 logging.warn("%s is running" % func.__name__)
 return func

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

foo = use_logging(foo)

foo() #  call 

This implementation USES decorators for Java mentioned in the previous article. The above is also a decorator that implements the simplest way to add a function log, but not if the extra function is to detect incoming parameters. This is where the example of the python decorator comes in handy in 12 steps.


#  A decorator 
def wrapper(func):
 def checker(a, b): # 1
  if a.x < 0 or a.y < 0:
   a = Coordinate(a.x if a.x > 0 else 0, a.y if a.y > 0 else 0)
  if b.x < 0 or b.y < 0:
   b = Coordinate(b.x if b.x > 0 else 0, b.y if b.y > 0 else 0)
  ret = func(a, b)
  if ret.x < 0 or ret.y < 0:
   ret = Coordinate(ret.x if ret.x > 0 else 0, ret.y if ret.y > 0 else 0)
  return ret
 return checker


#  The function 
def add(a, b):
 return Coordinate(a.x + b.x, a.y + b.y)

#  Use the adornment  
add = wrapper(add) 

If you are careful, you will notice that the parameters of the decorator function are the original function passed in, while the parameters of the inner function are the same as those of the original function 1. The outermost function returns the reference of the inner function, while the inner function returns the result of the reference call passed in

There are functions as parameter features, and of course there is some knowledge of closures, as shown in the blog links above, which are really good.

The Python decoration feature mentioned in the previous article is this magic syntax sugar and can be used like this


#  The function 
@wrapper
def add(a, b):
 return Coordinate(a.x + b.x, a.y + b.y)

A decorator with parameters

If You want to implement a decorator with parameters, how do you write it


def time_diff(s):
 def decorator(func):
  def wrapper(*args, **kwargs):
   start_time = time.time()
   res = func(*args, **kwargs)
   end_time = time.time()
   print("[%s] Time taken to execute the program : %s" % (s, end_time - start_time))
   return res
  return wrapper
 return decorator
 
@time_diff("polynomial_1")
def polynomial_1(n, x):
 res = 0
 for i in range(n):
  res += i*pow(x, i)
 return res

Call and execute the output:


print(polynomial_1(1, 5))

[duoxiangshi_1] Time taken to execute the program : 4.76837158203125e-06
0

A parameterized decorator needs to define a layer of functions outside of the parameterless decorator, and the outermost function returns a reference to the layer 2 function.

Conclusion: More practice, used in practice, can be more skilled. Recently, learning data structure and algorithm, write some decorators to see the execution time of the program, really convenient!


Related articles: