函数装饰器:
"在不改变原函数的基础上,给函数增加功能"把一个函数当作参数,返回一个替代版的函数
本质上:返回函数的函数
比如:我们的原函数是下图,(可以显示你要显示的年龄)
# 装饰器的概念
- 装饰器的实现是函数里面嵌套函数;
- 装饰器的本质是一个函数, 它可以让其他函数在不需要做任何代码改动的前提下增加额外的功能;
- 装饰器需要传递一个函数, 返回值也是一个函数对象.
# 装饰器的应用场景
- 计时器
- 记录日志
- 用户登录验证
- 函数参数验证
我们想在其前面加一个判定条件(如果显示的年龄小于0那么就让age=-0),但是我们不能改变原函数的内容,所以我们可以重新定义一个函数,如下图
这样我们就可以在不改变原函数的前提下,给函数增加新的功能。
但是一般不这么写。一般我们需要先创建好函数装饰器,然后给原函数加上语法糖就好。
如图(我们装饰器的需求:获取每个函数的执行时间,函数执行前计算时间,函数执行后计算时间)
我们可以看到,函数执行的结果后面计算出了函数运行所以需要的时间
问题1:我们上述的原函数中没有返回值,当函数有返回值时,我们需要在装饰器中做如下图改动(将执行函数赋值给一个变量,然后将此变量return就可以了)
问题2:如何保留被装饰函数的函数名和帮助文档信息,如下图
练习一:
创建装饰器, 要求如下:
1. 创建add_log装饰器, 被装饰的函数打印日志信息;
2. 日志格式为: [字符串时间] 函数名: xxx, 运行时间:xxx, 运行返回值结果:xxx
time.ctime()为字符串时间 time.time()为运行时间
练习二:
需求:验证用户登陆的装饰器is_login
1.如果用户登陆成功,则执行被装饰的函数
2.如果用户登陆不成功,则执行登陆函数
练习三(带有多个装饰器的函数):
需求: 判断登陆用户是否未管理员is_admin(此处管理员只有一个为:admin用户)
1).如果用户为管理员, 则执行被装饰的函数;
2).如果用户不是管理员, 则报错;
练习四(带有参数的函数装饰器):
练习五:(判断带有参数的函数装饰器的参数是否为整型,如果是则执行被装饰后的函数)
练习六:
编写装饰器required_types, 条件如下:
1). 当装饰器为@required_types(int,float)确保函数接收到的每一个参数都是int或者float类型;
2). 当装饰器为@required_types(list)确保函数接收到的每一个参数都是list类型;
3). 当装饰器为@required_types(str,int)确保函数接收到的每一个参数都是str或者int类型;
4). 如果参数不满足条件, 打印 TypeError:参数必须为xxxx类型