SoFunction
Updated on 2024-11-10

Python Decorator Knowledge Supplement

First of all, recalling the comments onPython Decorators and Decorator Patterns

make up a deficiency

According to the Java implementation of the decorator pattern, we can write the following piece of code:

import logging


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

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

foo = use_logging(foo)

foo() # call (programming)

This implementation uses decorators for Java as mentioned in the previous post. The above is also a decorator to implement the simplest one to increase the function logging, but if this additional function is to go to detect the incoming parameters, then the above will not work. At this point the example in 12 Easy Steps to Python Decorators is still subtle.

# Decorator
def wrapper(func):
 def checker(a, b): # 1
  if  < 0 or  < 0:
   a = Coordinate( if  > 0 else 0,  if  > 0 else 0)
  if  < 0 or  < 0:
   b = Coordinate( if  > 0 else 0,  if  > 0 else 0)
  ret = func(a, b)
  if  < 0 or  < 0:
   ret = Coordinate( if  > 0 else 0,  if  > 0 else 0)
  return ret
 return checker


# Original function
def add(a, b):
 return Coordinate( + ,  + )

# Use of decorations
add = wrapper(add) 

Carefully you will find that the parameters of the decorator function is the original function passed in, and the parameters of the internal function is exactly the same as the original function, the outermost return is a reference to the internal function, the internal function returns a reference to the incoming parameters of the result of the call

The function-as-argument feature is used here, and of course there's some closure knowledge, see the link to the blog mentioned above, it's really good.

The Python decoration feature mentioned in the last post is this amazing syntactic sugar, which can be used like this

# Original function
@wrapper
def add(a, b):
 return Coordinate( + ,  + )

Decorator with parameters

If one were to implement a decorator with parameters, how would one write the

def time_diff(s):
 def decorator(func):
  def wrapper(*args, **kwargs):
   start_time = ()
   res = func(*args, **kwargs)
   end_time = ()
   print("[%s] Time taken to execute 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

Decorators with parameters require another layer of functions to be defined outside of the decorator without parameters, and the return value of the outermost function is a reference to the second layer of functions.

In summary: more practice, used in practice, in order to be more skillful. Recently, I've been studying data structures and algorithms, and it's really convenient to write some decorators to see the execution time of the program!