在阅读代码中,发现@***的什么的,原来这个就是大名鼎鼎的装饰器,然后就学习了下装饰器,记录下学习心得。
python装饰器就是用于拓展原来函数功能的一种特殊的函数,特殊之处在于它返回的是一个函数。
优点:不用更改原代码前提下可以新增函数的功能。
应用场景:插入日志,性能测试,事务处理,提取大量函数中与本身功能无关的类似代码,达到代码重复使用的目的。
用例子说明事物是最好懂的。
首先亮出原代码
import time
def func():
print("hello")
time.sleep(1)
print("tian")
要求:记录函数的执行总时间
常规想法:更改原代码。
import time
def func():
startTime = time.time()
print("hello")
time.sleep(1)
print("tian")
endTime = time.time()
msecs = (endTime - startTime)*1000
print("time is %d ms" %msecs)
思考:如果使用装饰器呢?琢磨下面的代码就很好理解了。
import time
def decorator(fun):
def wrapper():
startTime = time.time()
fun()
endTime = time.time()
msecs = (endTime - startTime)*1000
print("time is %d ms" %msecs)
return wrapper
@decorator
def fun():
print("hello")
time.sleep(1)
print("tian")
if __name__=="__main__":
f=fun
f()
3.1 带参数的装饰器
import time
def decorator(fun):
def wrapper(a,b):
startTime=time.time()
fun(a,b)
endTime=time.time()
msecs=(endTime - startTime)*1000
print("time is %d ms" %msecs)
return wrapper
@decorator
def fun(a,b):
print("hello")
time.sleep(1)
print("result is %d" %(a+b))
if __name__=="__main__":
f=fun
f(3,4)
3.2 带有不定参数的装饰器
以*开头,可以传多个参数,**是形参中按照关键字传值把多余的传值以字典的方式呈现。
*args:表示将实参中按照位置传值,多出来的值都给args,且以元祖的方式呈现。
**kwargs:表示形参中按照关键字传值把多余的传值以字典的形式呈现
import time
def decorator(fun):
def wrapper(*args,**kwargs):
startTime=time.time()
fun(*args,**kwargs)
endTime=time.time()
msecs=(endTime - startTime)*1000
print("time is %d ms" %msecs)
return wrapper
@decorator
def fun1(a,b):
print("hello")
time.sleep(1)
print("result is %d" %(a+b))
@decorator
def fun2(a,b,c):
print("hello")
time.sleep(1)
print("result is %d" %(a+b+c))
if __name__=="__main__":
fun1(3,4)
fun2(3,4,5)
3.3 多个装饰器
#多个装饰器
import time
def deco01(func):
def wrapper(*args, **kwargs):
print("this is deco01")
startTime = time.time()
func(*args, **kwargs)
endTime = time.time()
msecs = (endTime - startTime)*1000
print("time is %d ms" %msecs)
print("deco01 end here")
return wrapper
def deco02(func):
def wrapper(*args, **kwargs):
print("this is deco02")
func(*args, **kwargs)
print("deco02 end here")
return wrapper
@deco01
@deco02
def func(a,b):
print("hello,here is a func for add :")
time.sleep(1)
print("result is %d" %(a+b))
if __name__ == '__main__':
f = func
f(3,4)
输出结果:
this is deco01
this is deco02
hello,here is a func for add :
result is 7
deco02 end here
time is 1000 ms
deco01 end here
Process finished with exit code 0
观察输出顺序可以大概推断执行的顺序。多个装饰器执行的顺序就是从最后一个装饰器开始,执行到第一个装饰器,再执行函数本身。
1 https://blog.csdn.net/xiangxianghehe/article/details/77170585
2 http://python.jobbole.com/82344/
3 https://www.cnblogs.com/xuyuanyuan123/p/6674645.html