大家好~我是
米洛
!
我正在从0到1打造一个开源的接口测试平台
, 也在编写与之配套的一套完整教程
,希望大家能够多多支持。
欢迎关注我的公众号米洛的测开日记
,获取最新文章教程!
# 装饰器
装饰器,很多人都会被这个名词震慑住,那它究竟是干嘛的,怎么使用
,原理
是什么呢?
先聊聊装饰器,装饰器我个人理解是Python的一种语法糖
,它常常用于方法调用之前/之后做的一些处理操作。
# 举个栗子🌰
计算方法执行时间
如果我要计算一个方法的执行时间,那我可以在方法调用之前记录下时间,执行完成后用
当前时间
-之前记录的时间
,这样就能拿到方法的执行时间
。日志、操作记录
我这个方法我想知道什么时候被调用了,有谁调用了,我都要记到
小本本
上,我们就可以用装饰器来帮我们做这个事情。判断用户是否登录
我们编写web系统常常会判断用户登录与否,没登录就不调用接口方法了,直接给他一个
需要登录
的提示,或者将用户跳转回登录页
。---所以呢,装饰器一般是在方法
执行之前
,执行之后
帮忙做一些工作。
# 先来看一个最简单的装饰器
我们想在方法执行之前打印一些话,执行之后也打印一些话。
def simple(func):
def wrapper():
print("开始了")
func()
print("结束了")
return wrapper
@simple
def func():
print("方法正在执行中")
if __name__ == "__main__":
func()
2
3
4
5
6
7
8
9
10
11
12
13
14
15
先看下结果:
# 解释
定义了一个simple方法,方法里面套了一层wrapper
方法,wrapper里面执行了func(),并在func执行之前/之后
都输出了对应的语句,最后返回了wrapper。
在对应的func
方法下面加上@simple,代表simple成为了func的一个装饰器。@
这个是装饰器的固定写法,大家不要惊慌,我们来拆解一下:
- func挂载了@simple,其实这一步等于:
simple(func)()
,不信我们去掉@simple,换成simple(func)试试。
def simple(func):
def wrapper():
print("开始了")
func()
print("结束了")
return wrapper
def func():
print("方法正在执行中")
if __name__ == "__main__":
simple(func)()
2
3
4
5
6
7
8
9
10
11
12
13
14
15
simple(func)()
我们进一步进行拆分,simple(func)这个返回了一个wrapper,而wrapper
还是一个方法!(看simple里面的def wrapper
)
所以我们拆分一下:
f = simple(func)
f()
2
simple(func)返回了一个f方法,f()则执行了返回的f
方法,所以合并到一起就是simple(func)()
,这样拆出来就更好理解了。
所以装饰器
的本质就是一个function而已,只不过@的写法会便捷很多
。不要再认为装饰器
是什么很高深的写法了,其实理解下来就是个套娃儿
的操作。
# 带参数的装饰器
关于带参数
的装饰器,其实原理也一样。
def simple(func):
def wrapper(*args, **kwargs):
print("开始了")
func(*args, **kwargs)
print("结束了")
return wrapper
@simple
def func(a, b, key="lihai"):
print(a, b, key)
print("方法正在执行中")
if __name__ == "__main__":
func(2, 4)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
可以看到,区别就是wrapper那儿加上了*args和**kwargs
,有这2个参数在,就可以囊括包裹方法的所有参数了。
之所以这么写,是为了让装饰器
能适配更多方法,其实我这么写,只对我一个方法生效,也是没问题
的,但是通用性就很差。
遇到参数不是a,b,key的,直接GG,装饰器无法继续使用
。
# 更多装饰器
相信大家一下子也不能轻易消化
,其实装饰器还有其他变种,比如类装饰器
,又或者装饰类的装饰器
。原来基本都类似。大家掌握了这里面的内容以后,就可以去了解下更多装饰器
的用法了,下一篇教大家怎么用装饰器
处理异步方法
。
觉得有用的话🔥记得点个关注❤️ 哦~
# 进阶的小作业
我想要一个循环执行N次方法的装饰器,命名为loop,如果@loop形式,则不进行循环,如果是@loop(5)
,则要循环方法5次,你可以试试吗?
@loop
def func1():
pass
@loop(5)
def func2():
pass
2
3
4
5
6
7