很多时候我们可能会有这样的需求,就是在调试的时候我们会想打印出某些变量出来看看程序对不对,然后在我们调试好了的时候再把这些print语句注释;这样做确实比较麻烦,我们在想有没有简单的方法:就是在需要打印的时候加上,同时不改变函数的内部代码
其实这就是装饰器的思想了:
decorators work as wrappers, modifying the behavior of the code before and after a target function execution, without the need to modify the function itself, augmenting the original functionality, thus decorating it.
函数
先从函数开始说起,python中函数常见的有如下几种用法:
1 把函数赋值给一个变量
2 在函数中定义函数
3 函数可以作为另外一个函数的参数
4 函数可以返回一个函数
2、4比较常见,1、3相对较少见,看下例子:
def hello(name):
return "hello," + name
hello_fn = hello
print(hello_fn("world"))
#outputs:
hello,world
def wrapper(func):
name = 'john'
return func(name)
print(wrapper(hello))
#outputs:
hello,john
从第二个例子中其实就有点decorator的意思了,要实现之前说的那个功能我们现在可以这样:
def logging(func,*args, **kwargs):
print('start logging...')
res=func(*args,**kwargs)
print('res=%s'%res)
print('end logging')
return res
logging(hello)
#outputs:
start logging...
res=hello,name
end logging
貌似还可以,但是其实还有更简单的做法,就是decorator.
用法很简单就是个语法糖,比如现在需要在四则运算开始前打印’start logging’,在运算之后打印’logging end’,可以先定义个logging函数实现打印的功能:
def logging(func):
def wrapper(*args, **kwargs):
print('start logging...')
res = func(*args, **kwargs)
print('res=%d' % res)
print('logging end.')
return res
return wrapper
接下来只要再调用,使用@就可以加上logging的功能
@logging
def add(x, y):
return x+y
add(3,4)
#outputs:
start logging...
res=7
logging end.
假设你还想把运算的结果变成平方,可以再写个函数:
def square_res(func):
def transfer(*args, **kwargs):
print('square res...')
res = func(*args, **kwargs)**2
print('square end.')
return res
return transfer
加下来调用就好:
@logging
@square_res
def add(x, y):
return x+y
add(3,4)
#outputs:
start logging...
square res...
square end.
res=49
logging end.
注意这里的顺序,先是square_res后是logging,@的写法刚好是相反的
写的很简单,也不太具体,只是想表达最简洁的意思和用法,想要了解的更具体的可以看: