Decorator 、 Faceted programming , Practical experience .
It's easy to learn from paper
Common functions , Our general return value is a common value or list , such as :
def mysum(a,b):
return a + b
result = mysum(1,2)
print(result)
mysum The function returns an integer 1+2 Value , by 3.
however python The magic place is , The return value of the function , It can be another function . such as :
def mysum_log():
print('input two number for sum ')
def mysum(a,b):
return a + b
return mysum
mysum2= mysum_log()
print(mysum2(1,2))
such ,mysum_log The function value of is a function , Assigned to variable mysum2, then print Direct use mysum2(1,2) You can run the function . At this time mysum2 The function is a little bit like mysum The function of , But added print function .
Running results :
input two number for sum
3
We can actually put variables mysum2 Direct change to mysum, Just change your name , The result is a little magical :
def mysum_log():
print('input two number for sum ')
def mysum(a,b):
return a + b
return mysum
mysum= mysum_log()
print(mysum(1,2))
So we look like we called mysum function , But in fact, we also print more logs print function . This is called closure in the industry – Who knows why it's called such a name , Thought the bag pi of .
What's the use ? It's no use just looking , But when this mysum The way was originally written by others , And people don't want to change his function , You can enrich the functions in this way .
for instance , Lao Wang next door wrote a function :
def laowangsum(a, b):
return a ^ 2 + b ^ 2
laowangsum The function of is to find the sum of squares , But there's no explanation , It's misleading , You ask Lao Wang to modify the function , Add notes , He is lazy and unwilling to move , What do I do ?
At this point, you think about whether you can steal the beam and change the column , Help him add some notes , Let your function call laowangsum Will add comments log. therefore :
def laowangsum(a, b):
return a ^ 2 + b ^ 2
def mysum_log():
print(' It was written by Lao Wang sum function , It's actually the sum of the squares of two numbers ')
return laowangsum
laowangsum = mysum_log()
print(laowangsum(1, 2))
You called laowangsum function , In fact, it runs your comments too much , Secretly changed the function of Lao Wang's function . This is the function of closures .
Another requirement : We require that log information be printed for each function , In order to locate which function is wrong in case of error . Or function large screen monitoring , What do I do ?
Add a write to each function log Code for ? High repeatability , We try to abstract it , Since closures can change function functions , That can be achieved with closures , But now the closure needs to specify the specific function , It is impossible to change the closure function when adding a new function in the future . At this point, the decorator is needed , Also called aspect programming . simply , I pass a variable representing a function into a closure function , Then the closure function can adaptively pass in the function , Call it automatically , You don't have to modify the closure every time you add a function , Just call the closure function once .
import functools
def log_decorator(function):
@functools.wraps(function)
def wrapper(*args,**kwargs):
print('log begin')
function(*args,**kwargs)
print('log end')
return wrapper
For example, when Lao Wang defined a function , Add a @log_decorator, You can automatically help him write his diary , He doesn't care about the log :
import functools
def log_decorator(function):
@functools.wraps(function)
def wrapper(*args,**kwargs):
print('log begin')
result = function(*args,**kwargs)
print('log end')
return result
return wrapper
@log_decorator
def laowangsum(a, b):
return a ^ 2 + b ^ 2
print(laowangsum(1, 2))
Running results :
log begin
log end
7
It can be seen that Lao Wang only realized the addition logic , But function runtime , But it automatically adds the function of writing logs , It's like the function was cut twice , Write is automatically added log Same function . So it is called aspect programming .
Also used print(laowangsum.name) Print out ,laowangsum It is really the function defined by Lao Wang himself , The name hasn't changed , Have not been cheated , the reason being that @functools.wraps(function) Why .
Except for functions , It can also be used for decoration , Be the same in essentials while differing in minor points . Replace functions with classes
class log:
def __init__(self,func):
self.func = func
self.num_calls = 0 # Number of function calls
def __call__(self, *args, **kwargs):
self.num_calls += 1
print('number of calls is :{}'.format(self.num_calls))
return self.func(*args, **kwargs)
@log
def example():
print('I am being called')
example()
example()
example()
result :
number of calls is :1
I am being called
number of calls is :2
I am being called
number of calls is :3
I am being called
log Class automatically helps to count the number of function calls .
Decorators are often used in :
1、 Write the log
2、 Statistics of running time
3、 Verify the validity of input data and user authentication