Python闭包指内层函数记住并引用外层函数的局部变量,即使外层函数已结束,变量仍驻留内存;需满足嵌套定义、引用外层局部变量、外层返回内层函数对象三条件。

Python闭包的核心在于:**内层函数记住了它被定义时所在作用域的变量,即使外层函数已经执行完毕,这些变量仍被保留在内存中供内层函数使用**。这不是简单的值拷贝,而是对变量对象的引用保持。
什么是闭包?三个必要条件
一个函数要构成闭包,必须同时满足:
- 存在嵌套函数(内层函数定义在外层函数内部)
- 内层函数引用了外层函数的局部变量(非全局、非参数传入)
- 外层函数返回了内层函数(不是调用结果,而是函数对象本身)
闭包如何保存状态?——freevars与__closure__
当满足闭包条件后,Python会自动为内层函数创建__closure__属性,它是一个元组,每个元素是cell对象,封装了被引用的外层变量。可通过func.__code__.co_freevars查看变量名。
例如:
立即学习“Python免费学习笔记(深入)”;
def make_adder(n):
def add(x):
return x + n # 引用了外层n
return add
plus3 = make_adder(3)
print(plus3.closure) # (| ,)
print(plus3.code.co_freevars) # ('n',)
print(plus3.closure[0].cell_contents) # 3
|
闭包 vs 普通嵌套:关键区别在变量生命周期
普通嵌套函数调用结束后,其局部变量随栈帧销毁;而闭包中的外层变量因被内层函数“捕获”,会延长生命周期,直到所有引用它的闭包函数对象被回收。
注意:闭包捕获的是变量的引用,不是快照。如果外层变量可变(如列表),后续修改会影响所有共享该闭包的函数:
def make_counter():
count = [0] # 用列表避免重新赋值
def inc():
count[0] += 1
return count[0]
return inc
c1 = make_counter()
print(c1()) # 1
print(c1()) # 2
常见陷阱:循环中创建多个闭包
在for循环中直接创建闭包,容易误以为每次捕获的是当前i值,实际捕获的是同一个变量i的最终值:
# ❌ 错误写法
funcs = []
for i in range(3):
funcs.append(lambda: i) # 全部返回2
✅ 正确写法:用默认参数固化当前值
funcs = []
for i in range(3):
funcs.append(lambda x=i: x)
或用闭包函数封装
def make_func(x):
return lambda: x
funcs = [make_func(i) for i in range(3)]










