闭包
# 闭包
闭包,又称闭包函数或者闭合函数,其实和嵌套函数类似,不同之处在于,闭包中外部函数返回的不是一个具体的值,而是一个函数。一般情况下,返回的函数会赋值给一个变量,这个变量可以在后面被继续执行调用。
闭包条件:
- 外部函数中定义了内部函数
- 外部函数一定要有返回值,返回的值是:内部函数名
- 内部函数引用了外部函数的变量
def func(a, b): # 101 99
c = 100
def inner_func(): # 1.外部函数中定义了内部函数
D = 20
print("闭包", a + b + c + D) # 3.内部函数引用了外部函数的变量
return inner_func # 2.外部函数一定要有返回值,返回的值是:内部函数名(不要加括号)
x = func(101, 99) # 接收的是内部函数的地址
x() # 调用内部函数
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
闭包的作用:
- 可以使用同级的作用域
- 读取其他元素的内部变量
- 延长作用域
闭包总结:
- 闭包似优化了变量,原来需要类对象完成的工作,闭包也可以完成。在外部函数中定义的变量,在内部函数可以直接访问
- 由于闭包引用了外部函数的局部变量,则外部函数的局部变量没有用时释放,消耗内存,因为变量不会被垃圾回收所以有一定的内存占用问题,作用域没有那么直观
- 闭包的好处,使代码变得简洁,便于阅读代码。
- 闭包是理解装饰器的基础
# python闭包的__closure__属性和 cell 对象
闭包比普通的函数多了一个 closure 属性,该属性记录着自由变量的地址。当闭包被调用时,系统就会根据该地址找到对应的自由变量,完成整体的函数调用。
以 nth_power() 为例,当其被调用时,可以通过 closure 属性获取自由变量(也就是程序中的 exponent 参数)存储的地址,例如:
def nth_power(exponent):
def exponent_of(base):
return base ** exponent
return exponent_of
square = nth_power(2)
# 查看 __closure__ 的值
print(square.__closure__) # (<cell at 0x000001B05AB820D8: int object at 0x0000000077948090>,)
print(type(square.__closure__[0])) # <class 'cell'>
print(square.__closure__[0].cell_contents) # 得到值2 # __closure__ 属性定义的是一个包含 cell 对象的元组,其中元组中的每一个 cell 对象用来保存作用域中变量的值。
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
可以看到,显示的内容是一个 int 整数类型,这就是 square 中自由变量 exponent 的初始值。还可以看到,closure 属性的类型是一个元组,这表明闭包可以支持多个自由变量的形式。
我们可以使用__closure__ 来检测函数是否是闭包. 使用函数名.__closure__返回cell就是闭包. 返回None就不是闭包
编辑 (opens new window)
上次更新: 2023/05/17, 23:08:21