🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
[TOC] ## 装饰器(Decorators) 装饰器,是**修改其他函数的功能的函数**。 `在原实现函数不修改的基础上,对原函数功能进行扩展。最终提供的调用方式保持一致。` ### 无参装饰器 假设现在线上有个函数`get_data` ```python def get_data(): print("I am getting data...") # 调用方式 get_data() ``` 运行结果是: ```cmd I am getting data... ``` 现在领导要求,下个版本开始,`get_data`需要先进行登录验证,获取到数据后,还要需要记录用户的操作日志。 在python中,有个神奇的功能,可以在不修改原函数的前提下,扩展修改原函数的功能。如下: ```python def wrapper(main_func): def inner(): print("login function called here.") main_func() print("log function called here.") return inner def get_data(): print("I am getting data...") # 调用方式 get_data = wrapper(get_data) get_data() ``` 运行结果是: ```cmd login function called here. I am getting data... log function called here. ``` 通过运行结果,已经实现了在获取数据前先进行了登录,获取数据后,又进行的日志打印。 再看一下修改情况,发现原来的`get_data`函数并没有修改,只是额外添加了一个`wrapper`函数。 **分析`wrapper`函数:** 1. wrapper函数接收一个函数对象`main_func`作为入参 2. wrapper函数在内部定义了一个内部函数`inner` *(在inner函数中,先处理了登录,然后调用了传入的`main_func`函数,最后处理日志打印)。* 3. 然后wrapper函数返回一个内部函数`inner`。 在调用`get_data` 的方式上,做了如下修改 ```python get_data = wrapper(get_data) get_data() ``` 先将get_data函数传递到wrapper函数中,获得内部函数inner,然后将inner赋值会给`get_data`,如此一来,执行`get_data()`,便等同于执行`inner()` 在python中,有种语法,叫**装饰器**,上面示例中,`wrapper`便可称为“装饰器”。我们可以用更加优雅的方式来调用装饰器,并且无需修改调用方式。 ```python def wrapper(main_func): def inner(): print("login function called here.") main_func() print("log function called here.") return inner @wrapper def get_data(): print("I am getting data...") # 调用方式 get_data() ``` 调用方式无需调整,原函数`get_data`无需调整,只需添加一个装饰器`wrapper`,然后再原函数`get_data`定义前,添加需要使用的装饰器 **`@wrapper`** 即可。 ### 带参装饰器 上面的例子,被修饰的函数没有带参数,装饰器本身也没有带参数。下面修改一下,让它们都可以带上参数。 ```python def wrapper(user, pwd): def outer(main_func): def inner(*args, **kwargs): print("login function called here.user=[%s],password=[%s]" % (user, pwd)) main_func(*args, **kwargs) print("log function called here.") return inner return outer @wrapper("gfc@126.com", "123456") def get_data(*args, **kwargs): print("I am getting data...") print(args) print(kwargs) # 调用方式 get_data("Milton", age=18) ``` 运行结果如: ```cmd login function called here.user=[gfc@126.com],password=[123456] I am getting data... ('Milton',) {'age': 18} log function called here. ``` 分析代码执行流程如下: **执行`get_data("Milton",age=18)`时:** 1. 先执行`wrapper("gfc@126.com","123456")`, 返回outer函数 ```python def outer(main_func): def inner(*args, **kwargs): print("login function called here.user=[%s],password=[%s]" % ("gfc@126.com", "123456")) main_func(*args, **kwargs) print("log function called here.") return inner ``` 2. 执行`outer(get_data)`,返回inner函数 ```python def inner(*args, **kwargs): print("login function called here.user=[%s],password=[%s]" % ("gfc@126.com", "123456")) get_data(*args, **kwargs) print("log function called here.") ``` 3. 执行`inner("Milton",age=18)` ```python print("login function called here.user=[%s],password=[%s]" % ("gfc@126.com", "123456")) get_data("Milton",age=18) print("log function called here.") ``` <hr style="margin-top:100px"> :-: ![](https://box.kancloud.cn/2ff0bc02ec938fef8b6dd7b7f16ee11d_258x258.jpg) ***微信扫一扫,关注“python测试开发圈”,了解更多测试教程!***