python闭包是内部函数引用外部非全局变量并被返回的函数对象,需满足嵌套定义、引用外部局部变量、返回内部函数三个条件,可借助__closure__属性验证。

Python闭包是指一个函数对象,它不仅包含函数本身,还“记住”了其定义时所在作用域中的变量(即使外层函数已执行完毕)。简单说:**内部函数引用了外部非全局变量,并被返回出去,就构成了闭包**。
闭包的三个必要条件
要形成闭包,必须同时满足:
- 存在嵌套函数(内部函数定义在外部函数内部)
- 内部函数引用了外部函数的局部变量(非 global,也非参数传入)
- 外部函数返回了内部函数(不是调用结果,而是函数对象本身)
如何验证一个函数是不是闭包
检查函数对象的 __closure__ 属性:如果为 None,说明不是闭包;否则是一个元组,每个元素是 cell 对象,可通过 .cell_contents 查看捕获的值。
例如:
立即学习“Python免费学习笔记(深入)”;
def make_adder(x):
def adder(y):
return x + y
return adder
<p>f = make_adder(10)
print(f.<strong>closure</strong>) # <cell at 0x...: int object at 0x...>
print(f.<strong>closure</strong>[0].cell_contents) # 输出 10
闭包的核心作用:延长变量生命周期 & 封装私有状态
外部函数执行完后,其局部变量本该销毁,但闭包让这些变量被内部函数“持有”,继续存活。这带来两个实用能力:
- 数据封装:避免使用全局变量,把配置、计数器、缓存等状态“绑定”在函数上
- 延迟绑定:闭包中引用的变量值,在内部函数真正调用时才取,不是定义时就固定
典型应用场景
1. 工厂函数生成定制化函数
比如生成不同基数的幂函数、带默认前缀的日志函数、按阈值过滤的判断器。
def make_power(n):
return lambda x: x ** n
<p>square = make_power(2)
cube = make_power(3)
print(square(4), cube(4)) # 16, 64
2. 计数器 / 状态保持
不依赖类或全局变量,实现轻量级有状态函数。
def make_counter():
count = 0
def counter():
nonlocal count
count += 1
return count
return counter
<p>c1 = make_counter()
print(c1(), c1(), c1()) # 1, 2, 3
3. 装饰器底层机制
@语法糖背后的装饰器函数,绝大多数都依赖闭包来接收被装饰函数并返回新函数。
def timer(func):
def wrapper(*args, **kwargs):
import time
start = time.time()
result = func(*args, **kwargs)
print(f"{func.__name__} took {time.time()-start:.3f}s")
return result
return wrapper # ← 这里返回的 wrapper 就是闭包
闭包不是语法糖,而是 Python 作用域规则和函数一等公民特性的自然体现。理解它,才能真正读懂很多库的实现逻辑和写出更灵活的函数式代码。










