偷学Python第二十三天:Python的装饰器
古之立大事者,不惟有超世之才,亦必有坚忍不拔之志。——苏轼
目标:可以用Python做一些简单的数据分析。
坚持完成自己的目标!勿忘初心~
今日学习目标
学习Python的装饰器
今日学习内容
装饰器
特点是函数是作为其参数出现的,装饰器还拥有闭包的特点
示例代码
"""
-*- coding:uft-8 -*-
author: 小甜
time:2020/5/22
"""
# 定义一个装饰器
def decorate(func):
def wrapper():
func()
print("已将学生加入学校学生名单")
print("已将学生加入系学生名单")
print("已将学生加入班级名单")
return wrapper
@decorate
def student():
print("我是小花")
student()
'''
---输出结果---
我是小花
已将学生加入学校学生名单
已将学生加入系学生名单
已将学生加入班级名单
'''
使用**
@
符号加函数名**来装饰一个函数执行流程:因为
student
是被装饰的函数,系统将student
函数以参数的形式传入decorate
函数(装饰器decorate
),执行decorate
函数,并将返回值赋给student
函数。
上一段代码等同于下面这段代码
"""
-*- coding:uft-8 -*-
author: 小甜
time:2020/5/22
"""
# 定义一个装饰器
def decorate(func):
def wrapper():
func()
print("已将学生加入学校学生名单")
print("已将学生加入系学生名单")
print("已将学生加入班级名单")
return wrapper
def student():
print("我是小花")
# 将返回值传给f 并调用
f = decorate(student) # 这里不能加(),不然就表示调用
f()
'''
---输出结果---
我是小花
已将学生加入学校学生名单
已将学生加入系学生名单
已将学生加入班级名单
'''
如果student
函数外有直接可执行的语句,在不调用student
函数的情况下,也会被执行,示例代码
"""
-*- coding:uft-8 -*-
author: 小甜
time:2020/5/22
"""
# 定义一个装饰器
def decorate(func):
print("这是外部的代码")
def wrapper():
func()
print("已将学生加入学校学生名单")
print("已将学生加入系学生名单")
print("已将学生加入班级名单")
return wrapper
@decorate
def student():
print("我是小花")
# student()
'''
---输出结果---
这是外部的代码
'''
应用场景
:可以用于电商网站的判断用户是否登录来是否继续往下执行;添加日志等场景
示例代码
"""
-*- coding:uft-8 -*-
author: 小甜
time:2020/5/22
"""
# 定义一个装饰器
def decorate(func):
def wrapper():
func()
print("正在检验用户是否登录")
# if # 判断是否登录的代码块
# pass
print("用户已登录")
return wrapper
@decorate # 使用装饰器
def add_shopping_cart():
print("添加成功")
@decorate # 使用装饰器
def payment():
print("付款成功")
add_shopping_cart()
payment()
'''
---输出结果---
添加成功
正在检验用户是否登录
用户已登录
付款成功
正在检验用户是否登录
用户已登录
'''
万能装饰器
因为函数的参数可能是不固定的,所以可以通过函数的可变参数来完成这种功能,可变参数的笔记看第六天,这是传送门
示例代码
"""
-*- coding:uft-8 -*-
author: 小甜
time:2020/5/22
"""
def decorate(func):
def wrapper(*args, **kwargs): # 使用可变参数来达到可以接受任何参数的效果
print("正在检测中。。。")
print(".............")
print("检测完毕")
func(*args, **kwargs)
return wrapper
@decorate # 使用装饰器
def f1(): # 无参数
print("这个没有任何功能")
@decorate
def f2(name): # 一个参数
print("名字是:", name)
@decorate
def student(*students): # 多个参数 # *students用于接收多个参数
for ch in students:
print(ch)
@decorate
def student_classroom(*students, classroom="可爱班"): # 接收可以赋值的参数
print(f"这是{classroom}的学生")
for ch in students:
print(ch)
# 调用函数
f1()
'''
---输出结果---
正在检测中。。。
.............
检测完毕
这个没有任何功能
'''
f2("甜甜")
'''
---输出结果---
正在检测中。。。
.............
检测完毕
名字是: 甜甜
'''
student("田野草莓", "樫野真", "花房五月")
'''
---输出结果---
正在检测中。。。
.............
检测完毕
田野草莓
樫野真
花房五月
'''
student_classroom("田野草莓", "樫野真", "花房五月", classroom="美丽班")
'''
正在检测中。。。
.............
检测完毕
这是美丽班的学生
田野草莓
樫野真
花房五月
'''
为了防止错误,在定义装饰器的时候要将其设置为万能装饰器
多层装饰器
"""
-*- coding:uft-8 -*-
author: 小甜
time:2020/5/22
"""
def maths(func): # 定义第一个装饰器
def wrapper(*args, **kwargs):
func(*args, **kwargs)
print("该学生已经学习了数学")
return wrapper
def Chinese(func): # 定义第而个装饰器
def wrapper(*args, **kwargs):
func(*args, **kwargs)
print("该学生已经学习了语文")
return wrapper
def English(func): # 定义第三个装饰器
def wrapper(*args, **kwargs):
func(*args, **kwargs)
print("该学生已经学习了英语")
return wrapper
@maths
@English
def student1(name):
print(f"学生{name}已经完成了")
@English
@Chinese
@maths
def student2(name):
print(f"学生{name}已经完成了")
# 调用函数
student1("小明")
'''
学生小明已经完成了
该学生已经学习了英语
该学生已经学习了数学
'''
student2("小花")
'''
学生小花已经完成了
该学生已经学习了数学
该学生已经学习了语文
该学生已经学习了英语
'''
多层的执行循序执行顺序是从里到外,最先调用最里层的装饰器,最后调用最外层的装饰器
带参数的装饰器
带参数的装饰器一共分为三层
第一层:负责接收装饰器的参数
第二层 :负责接收函数
第三层:负责接收函数的参数
"""
-*- coding:uft-8 -*-
author: 小甜
time:2020/5/22
"""
# 装饰器带参数
def outer(a): # 第一层: 负责接收装饰器的参数
def decorate(func): # 第二层 : 负责接收函数
def wrapper(*args, **kwargs): # 第三层 负责接收函数的参数
for i in range(a):
print(i)
func(*args, **kwargs)
return wrapper # 返出来的是:第三层
return decorate # 返出来的是:第二层
@outer(3)
def number():
print("打印完毕")
number()
'''
0
1
2
打印完毕
'''
最外层的函数负责接收装饰器参数
里面的内容还是原装饰器的内容
今日学习总结
Python的装饰器,使用@
来调用一个装饰器。需要注意的是装饰器的执行顺序是从里往外的
明日学习计划
学习函数的内置函数、匿名函数、递归函数
甜甜有话说
今天又学到了点东西,
座右铭:不要在该奋斗的年纪选择安逸!!