PY进阶——闭包与装饰器

闭包

在函数调用结束后,函数内定义的变量就销毁了,有时需要保存函数内变量(比如我需要记录函数调用次数)
使用外部函数变量的内部函数就叫做闭包
条件有嵌套、有引用、有返回
nonlocal引入外部函数变量(进行修改)

1
2
3
4
5
6
7
8
9
10
11
12
13
def fn():
num=0
def fn2():
nonlocal num #引入外部函数变量
num=num+1
print(num)
return fn2
if __name__ == '__main__':
f=fn()
f() #1
f2=fn()
f() #2
f2()#1

上述代码中f和f2中的num并不共用

装饰器

装饰器是特殊的闭包,其目的是不改变函数功能的情况下对函数做增强
构成装饰器的条件在闭包的条件下增加一个有额外功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
"""
语法1:
变量名=装饰器名(原有函数名)
变量名()
"""
def add_option(fn):
def option(txt):
#增加功能
print("add option")
fn(txt)
return option

def text(txt):
print(txt)
if __name__ == '__main__':
txt1 = "Hello World"
fn_text=add_option(text)
fn_text(txt1)
# add option
# Hello World

语法2:语法糖(@装饰器名),后直接调用原函数名

1
2
3
4
5
6
7
8
9
10
11
12
13
14
def add_option(fn):
#增加功能
def option(txt):
print("add option")
fn(txt)
return option
@add_option
def text(txt):
print(txt)
if __name__ == '__main__':
txt1 = "Hello World"
text(txt1)
# add option
# Hello World

注意装饰器的内部函数格式要与原函数保持一致
不定参有返回值函数装饰器

1
2
3
4
5
6
def add_option(fn):
#增加功能
def option(*args,**kwargs):
print("add option")
return fn(*args,**kwargs)
return option

多装饰器装饰

传统函数中离函数近的装饰器先装饰,由内到外

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
def add_option(fn):
#增加功能
def option(*args, **kwargs):
print("add option")
return fn(*args, **kwargs)
return option
def add_option1(fn):
#增加功能
def option(*args, **kwargs):
print("add option1")
return fn(*args, **kwargs)
return option

def text(txt):
print(txt)
return txt
if __name__ == '__main__':
txt1 = "Hello World"
text=add_option(text)
text=add_option1(text)#最靠近调用函数的先执行
text(txt1)
"""
add option1
add option
Hello World
"""

语法糖内则是按照语法糖顺序从上往下装饰

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
def add_option(fn):
#增加功能
def option(*args, **kwargs):
print("add option")
return fn(*args, **kwargs)
return option
def add_option1(fn):
#增加功能
def option(*args, **kwargs):
print("add option1")
return fn(*args, **kwargs)
return option

@add_option
@add_option1
def text(txt):
print(txt)
return txt
if __name__ == '__main__':
txt1 = "Hello World"
text(txt1)
"""
add option
add option1
Hello World
"""

单装饰器多函数(多参装饰器)

装饰器只能传递一个参数也就是函数,要传入多一个参数就要在外层多传递一个参数
即改造为嵌套装饰

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 choice(flag):
def add_option(fn):
# 增加功能
def option(*args, **kwargs):
if flag==1:#判断
print("txt1")
elif flag==2:
print("txt2")
#返回装饰后函数
return fn(*args, **kwargs)
#返回内部函数
return option
#返回装饰器
return add_option
@choice(1)
def text(txt):
print(txt)
return txt
@choice(2)
def text2(txt):
print(txt+'2')
return txt
if __name__ == '__main__':
txt1 = "Hello World"
text(txt1)
text2(txt1)
"""
txt1
Hello World
txt2
Hello World2
"""

上述代码如果不嵌套,也可等同于

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 add_option(fn):
#增加功能
def option(*args, **kwargs):
if fn.__name__ == "text": # 判断
print("txt1")
elif fn.__name__ == "text2":
print("txt2")
return fn(*args, **kwargs)
return option
@add_option
def text(txt):
print(txt)
return txt
@add_option
def text2(txt):
print(txt+'2')
return txt
if __name__ == '__main__':
txt1 = "Hello World"
text(txt1)
text2(txt1)
"""
txt1
Hello World
txt2
Hello World2
"""

深浅拷贝

数据类型中存在可变类型(列表、字典、集合)与不可变类型
深浅拷贝是针对可变类型
浅拷贝只拷贝了对象本省,内部的元素只拷贝了一个引用(即仍指向原数据存放的堆)
对不可变类型使用深浅拷贝,效果和直接赋值一样
浅拷贝:copy()
深拷贝:deepcoy()


PY进阶——闭包与装饰器
http://example.com/2026/03/25/PY进阶——闭包与装饰器/
作者
印星
发布于
2026年3月25日
许可协议