
闭包是指在一个嵌套函数中,内部函数引用了外部函数的变量,并且外部函数返回了内部函数。闭包会“记住”外部函数的变量,即使外部函数已经执行完毕。
一、什么是闭包
1. 基本结构
def outer(x):
def inner(y):
return x + y
return inner
# 创建闭包
add_5 = outer(5)
result = add_5(3)
print(result) # 8
关键要素:
存在嵌套函数(inner)
内部函数引用了外部函数的变量(x)
外部函数返回了内部函数
2. 闭包的本质
def outer(x):
def inner(y):
return x + y
return inner
add_5 = outer(5)
add_10 = outer(10)
print(add_5(3)) # 8
print(add_10(3)) # 13
# 查看闭包捕获的变量
print(add_5.__closure__) # (<cell at 0x…: int object at 0x…>,)
print(add_5.__closure__[0].cell_contents) # 5
二、闭包的特点
1. 记住外部变量的值
def counter():
count = 0
def increment():
nonlocal count
count += 1
return count
return increment
c1 = counter()
c2 = counter()
print(c1()) # 1
print(c1()) # 2
print(c1()) # 3
print(c2()) # 1(独立的闭包,有自己的 count)
2. 延迟计算
def make_power(exponent):
def power(base):
return base ** exponent
return power
square = make_power(2) # 平方函数
cube = make_power(3) # 立方函数
print(square(5)) # 25
print(cube(5)) # 125
三、闭包的实现原理
1. __closure__ 属性
每个闭包函数都有一个 __closure__ 属性,存储捕获的外部变量。
def outer(x, y):
z = 100
def inner():
return x + y + z
return inner
func = outer(10, 20)
# 查看闭包捕获的变量
print(func.__closure__)
# (<cell at 0x…: int object at 0x…>,
# <cell at 0x…: int object at 0x…>,
# <cell at 0x…: int object at 0x…>)
# 查看捕获的值
for cell in func.__closure__:
print(cell.cell_contents) # 10, 20, 100
2. __code__.co_freevars 自由变量
def outer(x):
def inner(y):
return x + y
return inner
func = outer(10)
print(func.__code__.co_freevars) # ('x',)
print(func.__code__.co_varnames) # ('y',)
四、闭包 vs 类
闭包在某些场景可以作为轻量级的替代方案。
# 使用闭包实现计数器
def counter_closure():
count = 0
def increment():
nonlocal count
count += 1
return count
return increment
# 使用类实现计数器
class CounterClass:
def __init__(self):
self.count = 0
def increment(self):
self.count += 1
return self.count
# 闭包更简洁
c1 = counter_closure()
print(c1()) # 1
# 类更明确
c2 = CounterClass()
print(c2.increment()) # 1
| 代码量 | 少 | 多 |
| 可读性 | 简单场景好 | 复杂场景好 |
| 状态 | 通过 nonlocal 修改 | 通过 self 修改 |
| 方法数量 | 单个函数 | 可以有多个方法 |
| 适用场景 | 简单状态保存 | 复杂业务逻辑 |
五、调试闭包
def outer(x, y):
z = 100
def inner(w):
return x + y + z + w
return inner
func = outer(10, 20)
# 1. 查看闭包中捕获的变量名
print(func.__code__.co_freevars) # ('x', 'y', 'z')
# 2. 查看闭包中捕获的值
for cell in func.__closure__:
print(cell.cell_contents) # 10, 20, 100
# 3. 查看函数的局部变量名
print(func.__code__.co_varnames) # ('w',)
六、其他
| 定义 | 函数+捕获的外部变量 |
| 条件 | 嵌套函数 + 引用外部变量 + 返回内部函数 |
| 捕获方式 | 按引用捕获(不是按值) |
| 内存 | 外部变量不会随函数结束而销毁 |
| 访问 | 读:直接访问;写:需要 nonlocal |
| 常见应用 | 装饰器、计数器、缓存 |
核心:
闭包会记住外部函数的变量
每次调用外部函数都会创建新的闭包实例
修改外部变量需要 nonlocal 关键字
闭包是装饰器的底层实现原理





