服务器之家

服务器之家 > 正文

Python装饰器详情

时间:2022-02-23 00:00     来源/作者:一碗周

1、装饰器

装饰器(Decorator):从字面上理解,就是装饰对象的器件。可以在不修改原有代码的情况下,为被装饰的对象增加新的功能或者附加限制条件或者帮助输出。

装饰器的特点是特点是函数是作为其参数出现的,装饰器还拥有闭包的特点。

示例代码如下所示:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 定义一个装饰器
def decorate(func):
    def wrapper():
        func()
        print("已将学生加入学校学生名单")
        print("已将学生加入系学生名单")
        print("已将学生加入班级名单")
 
    return wrapper
 
 
@decorate
def student():
    print("我是小花")
 
 
student()
'''
---输出结果---
我是小花
已将学生加入学校学生名单
已将学生加入系学生名单
已将学生加入班级名单
'''

使用**@****符号加函数名**来装饰一个函数

执行流程:因为student是被装饰的函数,系统将student函数以参数的形式传入decorate函数(装饰器decorate),执行decorate函数,并将返回值赋给student函数。

上一段代码等于下面这一段代码:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 定义一个装饰器
def decorate(func):
    def wrapper():
        func()
        print("已将学生加入学校学生名单")
        print("已将学生加入系学生名单")
        print("已将学生加入班级名单")
 
    return wrapper
 
 
def student():
    print("我是小花")
 
 
# 将返回值传给f 并调用
f = decorate(student)  # 这里不能加(),不然就表示调用
f()
'''
---输出结果---
我是小花
已将学生加入学校学生名单
已将学生加入系学生名单
已将学生加入班级名单
'''

如果student函数外有直接可执行的语句,在不调用student函数的情况下,也会被执行,

示例代码如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 定义一个装饰器
def decorate(func):
    print("这是外部的代码")
 
    def wrapper():
        func()
        print("已将学生加入学校学生名单")
        print("已将学生加入系学生名单")
        print("已将学生加入班级名单")
 
    return wrapper
 
 
@decorate
def student():
    print("我是小花")
 
 
# student()
'''
---输出结果---
这是外部的代码
'''

1.1 应用场景

可以用于电商网站的判断用户是否登录来是否继续往下执行;添加日志等场景,

示例代码如下所示:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# 定义一个装饰器
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、万能装饰器

因为函数的参数可能是不固定的,所以可以通过函数的可变参数来完成这种功能。

示例代码如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
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、多层装饰器

多层的执行循序执行顺序是从里到外,最先调用最里层的装饰器,最后调用最外层的装饰器,

示例代码如下所示:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
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、带参数的装饰器

带参数的装饰器一共分为三层,分别如下:

  • 第一层:负责接收装饰器的参数
  • 第二层 :负责接收函数
  • 第三层:负责接收函数的参数

示例代码如下所示:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# 装饰器带参数
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装饰器详情的文章就介绍到这了,更多相关Python装饰器内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://juejin.cn/post/7024045904214622222

标签:

相关文章

热门资讯

蜘蛛侠3英雄无归3正片免费播放 蜘蛛侠3在线观看免费高清完整
蜘蛛侠3英雄无归3正片免费播放 蜘蛛侠3在线观看免费高清完整 2021-08-24
2022年最旺的微信头像大全 微信头像2022年最新版图片
2022年最旺的微信头像大全 微信头像2022年最新版图片 2022-01-10
背刺什么意思 网络词语背刺是什么梗
背刺什么意思 网络词语背刺是什么梗 2020-05-22
yue是什么意思 网络流行语yue了是什么梗
yue是什么意思 网络流行语yue了是什么梗 2020-10-11
2020微信伤感网名听哭了 让对方看到心疼的伤感网名大全
2020微信伤感网名听哭了 让对方看到心疼的伤感网名大全 2019-12-26
返回顶部