[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测试开发圈”,了解更多测试教程!***
- 前言
- chapter01_开发环境
- chapter02_字符串的使用
- chapter03_列表的使用
- chapter04_字典的使用
- chapter05_数字的使用
- chapter06_元组的使用
- chapter07_集合的使用
- chapter08_输入输出
- chapter09_控制流程
- chapter10_实例练习_登录1
- chapter11_python函数入门
- chapter12_python中的类
- chapter13_轻松玩转python中的模块管理
- chapter14_掌握学习新模块的技巧
- chapter15_通过os模块与操作系统交互
- chapter16_子进程相关模块(subprocess)
- chapter17_时间相关模块(time & datetime)
- chapter18_序列化模块(json)
- chapter19_加密模块(hashlib)
- chapter20_文件的读与写
- chapter21_阶段考核2_登录
- chapter22_小小算法挑战(排序&二分法)
- chapter23_用多线程来搞事!
- chapter24_HTTP接口请求(requests)
- chapter25_接口测试框架(pytest)
- chapter26_阶段考核3_HTTP接口测试
- chapter27_HTML解析(pyquery)
- chapter28_阶段考核4_爬虫下载网易汽车
- chapter29_python中的那些编码坑
- chapter30_MySQL数据库操作
- chapter31 高级特性_迭代器与生成器
- chapter32 高级特性_装饰器
- chapter33 高级特性_列表处理