1、对闭包和装饰器的理解
先来介绍下 装饰器的用途,为什么要使用装饰器
假如有这么个功能,来计算耗时:
def add():
start_time = time.time()
time.sleep(3)
end_time = time.time()
print("耗时:{}".format(end_time - start_time))
return None
if __name__ == "__main ":
add(1, 3)
疑问:会发现,如果我有多个应用需要计时,那就需要写很多的重复代码,这时候就可以使用装饰器来操作:
# 定义一个方法,接收一个函数,在python中一切皆对象,函数也可以用来做参数赋值等
# 需要理解python装饰器加载的过程和闭包
# 新建一个test.py
import time
def time_desc(func):
print("装饰器")
start_time = time.time()
func()
end_time = time.time()
print("耗时:{}".format(end_time - start_time))
# return a + b
@time_desc
def add():
time.sleep(3)
return None
python test.py 运行后,发现函数time_desc,执行了,控制台输入了日志
装饰器
耗时:3.000149965286255
耗时:3.000149965286255
我们并没有运行 time.desc 方法,那它为什么执行了呢?
事实证明了,在执行或者调用了这个模块里有装饰器,那python的这个@语法糖就直接运行了这个函数,所以我们才需要把
装饰器,写成闭包的形式
改写成:
import time
def time_desc(func):
def wrapper():
print("装饰器")
start_time = time.time()
func()
end_time = time.time()
print("耗时:{}".format(end_time - start_time))
return wrapper # 注意 此处不是 wrapper() 不是调用
@time_desc
def add():
time.sleep(3)
return None
这就是装饰器的由来;
还有需要注意:
(1)经语法糖@装饰器后,返回的其实是wrapper,如果你调用 add() 其实是执行了装饰器 wrapper方法,
(2)如果add(a,b) 有参数的话,那装饰器 wrapper(*args, **kwargs),来解决参数问题
本博客源码Github地址:
请随手给个star,谢谢!