闭包_装饰器_深浅拷贝
闭包背景介绍
1 | """ |
闭包入门
1 | # 定义一个用于求和的闭包。 |
nonlocal关键字介绍
代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19"""
nonlocal:
他是一个python内置的关键字,可以实现在内部函数中,修改外部函数的变量值
编写一个闭包,让内部函数去访问外部函数内的参数a = 100,观察效果。
"""
def fn_outer():
a = 100 # 有嵌套
def fn_inner():
# a = a + 1 # 有引用 #生命周期不同
nonlocal a
a=a+1
print(f"a:{a}")
return fn_inner
if __name__ == '__main__':
a = fn_outer()
a() # 101
a() #102
a() #103
装饰器入门
图解
代码
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# 例如,发表评论前,都是需要先登录的。
# 先定义有发表评论的功能函数,然后在不改变原有函数的基础上,
# 需要提示用户要先登录。
"""
装饰器介绍:
概述/作用:
他的本质是一个闭包函数,目的:就是在不改变原有函数的基础上,对其功能做了增强
前提条件:
1:有嵌套
2:有引用
3:有返回
4:有额外功能
装饰器的用法:
格式1:传统写法
装饰后的函数名=装饰器名(被装饰的原函数名)
装饰后的函数名() !!!一般修饰前和修饰后的函数名保持一致
格式2:语法糖 (推荐)
在要被装饰的原函数头上,直接@装饰器名,直接调用原函数即可
"""
# 编写装饰器
def check_login(fn_name):
# 1.1定义内部函数
def fn_inner(): # 有嵌套
# 1.2增加额外功能
print("校验登录.....登录成功") # 有引用
# 1.3访问原函数 , 即外部函数的引用
fn_name()
# 1.4返回内部函数对象(名)
return fn_inner
def comment():
print("发表评论")
if __name__ == '__main__':
#1:传统写法
# 装饰后的函数名 = 装饰器名(被装饰的原函数名)
# 装饰后的函数名() !!!一般修饰前和修饰后的函数名保持一致
#!!!一般修饰前和修饰后的函数名保持一致
# # 修饰后 修饰前
# comment = check_login(comment)
# comment()
#2:语法糖
comment()
装饰器案例
场景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
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"""
在无参无返回值的原有函数求和
计算结果之前,添加一个友好提示(注意:不能改变源码):正在努力计算中...。
细节:
1:装饰的内部函数格式要和被装饰器的原函数保持一致
解释:
1-1:原函数是无参无返回值的。则装饰器的内部函数也必须是无参无返回值。
1-2:原函数是有参有返回值的,则装饰器的内部函数必须也是有参有返回值。
"""
# 添加一个友好提示(注意:不能改变源码):正在努力计算中...。
# 完成一个可以有提示功能的装饰器
# 【装饰器】
def my_sum(fn_name):
def fn_inner():
print("正在努力计算中.....")
fn_name()
return fn_inner
# 【原函数】在参无返回值的原有函数求和
def get_sum():
a = 10
b = 20
sum = a + b
print(f"sum求和结果:{sum}")
"""
在无参无返回值的原有函数求和
计算结果之前,添加一个友好提示(注意:不能改变源码):正在努力计算中...。
细节:
1:装饰的内部函数格式要和被装饰器的原函数保持一致
解释:
1-1:原函数是无参无返回值的。则装饰器的内部函数也必须是无参无返回值。
1-2:原函数是有参有返回值的,则装饰器的内部函数必须也是有参有返回值。
"""
# 添加一个友好提示(注意:不能改变源码):正在努力计算中...。
# 完成一个可以有提示功能的装饰器
# 【装饰器】
def my_sum(fn_name):
def fn_inner(): # 有嵌套
print("正在努力计算中.....") # 有额外功能
fn_name() # 有引用
return fn_inner # 有返回值
# 【原函数】在参无返回值的原有函数求和
def get_sum():
a = 10
b = 20
sum = a + b
print(f"sum求和结果:{sum}")
if __name__ == '__main__':
# get_sum = my_sum(get_sum)
# get_sum()
get_sum()场景2: ==有参无返回值的原函数==
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18# 在有参无返回值的原有函数求和计算结果之前,
# 添加一个友好提示(注意:不能改变源码):正在努力计算中...。
# 【装饰器】
def my_sum(fn_name):
def fn_inner(x, y): # 有嵌套
print("正在努力计算中....") # 有增强
fn_name(x,y) # 有引用
return fn_inner # 有返回
# 【原函数】
# @my_sum
def get_sum(a, b):
sum = a + b
print(f"sum求和结果:{sum}")
if __name__ == '__main__':
# get_sum(10,20)
get_sum=my_sum(get_sum)
get_sum(10,20)场景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"""
在无参有返回值的原有函数求和计算结果之前,添加一个友好提示(注意:不能改变源码):正在努力计算中...。
在有参有返回值的原有函数求和计算结果之前,添加一个友好提示(注意:不能改变源码):正在努力计算中...。
"""
# 在无参有返回值的原有函数求和计算结果之前,添加一个友好提示(注意:不能改变源码):正在努力计算中...。
# 【装饰器】 有嵌套、 有引用 、有返回值、有增加功能
def my_sum(fn_name):
def fn_inner():
print("正在努力计算中...。")
return fn_name() # 有引用
return fn_inner
# 【原函数】
# @my_sum
def get_sum(): # 无参有返回值
a = 10
b = 20
return a + b
# 两种写法
# 传统写法
get_sum=my_sum(get_sum)
print(get_sum())
# 语法糖
# print(get_sum())
# gs = get_sum()
# print(gs)场景4:==有参有返回值装饰器==
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19# 在有参有返回值的原有函数求和计算结果之前,
# 添加一个友好提示(注意:不能改变源码):正在努力计算中...。
# 【装饰器】
def my_sum(fn_name):
def fn_inner(x,y):
print("正在努力计算中...。")
return fn_name(x,y) #有返回值,有引用
return fn_inner
# 【原函数:有参、有返回值】
def get_sum(a, b):
return a + b
print(get_sum(20, 20))场景5:==不定长参数装饰器==
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# 定义一个可以计算多个数据和多个字典value值之和的函数,并调用。
# 在原有函数的计算结果之前,加一个友好提示(不能改变源码):正在努力计算中...。
# 【2.装饰器】
def my_sum(fn_name):
def fn_inner(*args,**kwargs):
print("正在努力计算中...。")
return fn_name(*args,**kwargs)
return fn_inner
# 【1.原函数】
#取结果之和
# @my_sum
def get_sum(*args,**kwargs):
# args 数据元组
# **kwargs 字典
# 定义求和计数器
sum= 0
#遍历获取元组中的值
for i in args:
sum+=i
for v in kwargs.values():
sum+=v
return sum
# return sum(args)+sum(kwargs.values())
if __name__ == '__main__':
get_sum=my_sum(get_sum)
# get_sum()
print(get_sum(1, 2, 3, a=4, b=5, c=6)场景6:==多个装饰器装饰一个函数==
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"""
例如,发表评论前,都是需要 先登录用户 再进行 验证码验证。
先定义有发表评论的功能函数,然后在不改变原有函数的基础上,需要先检查用户登录和输入验证码。
记忆: 多个装饰器装饰一个原函数,就按照 由内向外的顺序来装饰
但是你要用装饰器写法来做的话,看到的效果是从上往下执行
"""
# 【装饰器check_login】
def check_login(fn_name):
def fn_inner():
print("校验登录")
fn_name()
return fn_inner
# 【装饰器check_code】
def check_code(fn_name):
def fn_inner():
print("校验验证码")
fn_name()
return fn_inner
# 【原函数:comment】
def comment():
print("发表评论")
# 【测试】
# 传统方法
# A
comment = check_code(comment)
comment=check_login(comment)
comment()
# B
# comment=check_login(comment)
# comment = check_code(comment)
# comment()
# comment()场景7:==一个装饰器装饰多个函数==
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"""
定义一个既能装饰减法运算,又能装饰加法运算的装饰器,即带有参数的装饰器。
记忆:
1:1个装饰器的参数有且只能有1个
2:如果装饰器有多个参数,可以在该装饰器外面在包裹一层装饰器,把该装饰器当做内部函数即可
"""
# 【装饰器】
def my_sum_sub(fn_name):
def fn_inner(a,b):
print("正在努力计算中.....")
return fn_name(a,b)
return fn_inner
# 【原函数】
def get_sum(a, b):
return a + b
def get_sub(a, b):
return a - b
if __name__ == '__main__':
print(get_sum(10,20))
print(get_sub(10, 20))场景8:==一个装饰器装饰多个函数嵌套版==
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# 【装饰器】
def logging(flag):
# 定义内部函数 ,格式要和原函数保持一致 参数和返回值
def my_sum_sub(fn_name):
def fn_inner(a, b):
if flag == "+":
print("正在努力计算【加法】中")
elif flag == "-":
print("正在努力计算【减法】中")
return fn_name(a, b)
return fn_inner
return my_sum_sub
# 【原函数】
# @logging('+')
def get_sum(a, b):
return a + b
# @logging('-')
def get_sub(a, b):
return a - b
#
#
# # __name___
# sub_str = logging("+")
# get_sum_sub = sub_str(get_sub)
# print(get_sum_sub(10, 5))场景9:==一个装饰器装饰多个函数魔法方法==
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19# 【装饰器】
def my_sum_sub(fn_name):
def fn_inner(a, b):
if fn_name.__name__ == "get_sum":
print("正在努力计算【加法】中")
elif fn_name.__name__ == "get_sub":
print("正在努力计算【减法】中")
return fn_name(a, b)
return fn_inner
# 【原始】
def get_sum(a, b):
return a + b
def get_sub(a, b):
return a - b
if __name__ == '__main__':
print(get_sum(10, 20))
print(get_sub(30,60))
All articles on this blog are licensed under CC BY-NC-SA 4.0 unless otherwise stated.