Python装饰器详情
作者:一碗周 发布时间:2021-10-22 07:22:49
标签:Python,装饰器
1、装饰器
装饰器(Decorator
):从字面上理解,就是装饰对象的器件。可以在不修改原有代码的情况下,为被装饰的对象增加新的功能或者附加限制条件或者帮助输出。
装饰器的特点是特点是函数是作为其参数出现的,装饰器还拥有闭包的特点。
示例代码如下所示:
# 定义一个装饰器
def decorate(func):
def wrapper():
func()
print("已将学生加入学校学生名单")
print("已将学生加入系学生名单")
print("已将学生加入班级名单")
return wrapper
@decorate
def student():
print("我是小花")
student()
'''
---输出结果---
我是小花
已将学生加入学校学生名单
已将学生加入系学生名单
已将学生加入班级名单
'''
使用**@
****符号加函数名**来装饰一个函数
执行流程:因为student
是被装饰的函数,系统将student
函数以参数的形式传入decorate
函数(装饰器decorate
),执行decorate
函数,并将返回值赋给student
函数。
上一段代码等于下面这一段代码:
# 定义一个装饰器
def decorate(func):
def wrapper():
func()
print("已将学生加入学校学生名单")
print("已将学生加入系学生名单")
print("已将学生加入班级名单")
return wrapper
def student():
print("我是小花")
# 将返回值传给f 并调用
f = decorate(student) # 这里不能加(),不然就表示调用
f()
'''
---输出结果---
我是小花
已将学生加入学校学生名单
已将学生加入系学生名单
已将学生加入班级名单
'''
如果student
函数外有直接可执行的语句,在不调用student
函数的情况下,也会被执行,
示例代码如下:
# 定义一个装饰器
def decorate(func):
print("这是外部的代码")
def wrapper():
func()
print("已将学生加入学校学生名单")
print("已将学生加入系学生名单")
print("已将学生加入班级名单")
return wrapper
@decorate
def student():
print("我是小花")
# student()
'''
---输出结果---
这是外部的代码
'''
1.1 应用场景
可以用于电商网站的判断用户是否登录来是否继续往下执行;添加日志等场景,
示例代码如下所示:
# 定义一个装饰器
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()
'''
---输出结果---
添加成功
正在检验用户是否登录
用户已登录
付款成功
正在检验用户是否登录
用户已登录
'''
2、万能装饰器
因为函数的参数可能是不固定的,所以可以通过函数的可变参数来完成这种功能。
示例代码如下:
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="前端班")
'''
正在检测中。。。
.............
检测完毕
这是前端班的学生
张三
李四
王五
'''
为了防止错误,在定义装饰器的时候要将其设置为万能装饰器
3、多层装饰器
多层的执行循序执行顺序是从里到外,最先调用最里层的装饰器,最后调用最外层的装饰器,
示例代码如下所示:
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("小花")
'''
学生小花已经完成了
该学生已经学习了数学
该学生已经学习了语文
该学生已经学习了英语
'''
4、带参数的装饰器
带参数的装饰器一共分为三层,分别如下:
第一层:负责接收装饰器的参数
第二层 :负责接收函数
第三层:负责接收函数的参数
示例代码如下所示:
# 装饰器带参数
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
打印完毕
'''
最外层的函数负责接收装饰器参数,里面的内容还是原装饰器的内容。
来源:https://juejin.cn/post/7024045904214622222


猜你喜欢
- 一个简单的php文件下载源代码,虽不支持断点续传等,但是可以满足一些常用的需求了。php下载文件其实用一个a标签就能实现,比如 <a
- 如今WEB的安全问题影响着整个安全界,SQL注入,跨站脚本攻击等攻击受到了关注。 网络安全问题日益变的更加重要,国内依然有很多主机受到此类安
- 现在视频号非常火热,之前在做抖音和快手的人就直接把之前的视频直接搬运过来了。但是从抖音app下载的视频都是带官方水印的?这个是怎么去掉的?哦
- 前言:在fastapi中,我们定义的查询参数是可以设置成:必选参数 or 可选参数。可选查询参数只要给查询参数的默认值设置为None,表示该
- 主要使用json模块,直接导入import json即可。小例子如下:#coding=UTF-8 import json info={} i
- 简洁优雅的 C 写法:int a = 1; int b = 2; int temp; temp = a;&nb
- 首先还是应该科普下函数参数传递机制,传值和传引用是什么意思?函数参数传递机制问题在本质上是调用函数(过程)和被调用函数(过程)在调用发生时进
- sys;//系统管理员,拥有最高权限 system;//本地管理员,次高权限 scott;//普通用户,密码默认为tiger,默认未解锁 s
- 问题:每次打开pycharm打开py文件光标都是insert模式, 像下面图片那样解决方案:讲Tools里面的Vim Emulator勾选去
- jQuery能够极大提高html的编写效率,其中checkbox的选中判断有几种:1, $(checkbox的id).prop("
- Page Object模式是Selenium中的一种测试设计模式,主要是将每一个页面设计为一个Class,其中包含页面中需要测
- 第一步:python中安装selenium库和其他所有Python库一样,selenium库需要安装pip install selenium
- 做渗透测试的时候,有个比较大的项目,里面有几百个网站,这样你必须首先确定哪些网站是正常,哪些网站是不正常的。所以自己就编了一个小脚本,为以后
- 原文地址:30 Days of Mootools 1.2 Tutorials - Day 6 - Manipulating HTML通过Mo
- 一、ESlint+Vetur 实现ESlint代码规范二、重点----旧版本(旧版本配置在setting.json 会出现警告){“esli
- 思路整理:1、进入心灵鸡汤网页,使用python获取心灵鸡汤内容2、登陆微信,找到需要发送的朋友3、发送获取的内容1、获取心灵鸡汤的内容如下
- 由于pygame.movie.Movie.play() 只支持MPEG格式的视频,且 pygame版本大于1.9.5好像已经不支持这个模块了
- 验证码是根据随机字符生成一幅图片,然后在图片中加入干扰象素,用户必须手动填入,防止有人利用机器人自动批量注册、灌水、发垃圾广告等等 。数据集
- 1.el-input无法输入的问题原因1、el-input组件没有绑定双向响应式数据(v-model)解决方案:在data中定义一个变量,然
- 获取页面的编码,如果是IE浏览器用document.charset即可获取,如果用firefox需要用document.characterS