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!