闭包由语言自动构建,需同时满足三条件:函数嵌套、内部函数引用外部局部变量、外部函数返回内部函数对象;词法作用域决定引用关系,nonlocal仅用于修改;可通过__closure__属性验证。

闭包的构建不是靠“手动绑定”或额外声明,而是由 Python(或 JavaScript 等支持闭包的语言)在函数定义和返回过程中自动完成的。关键在于三个动作同时发生:嵌套、引用、返回。
必须满足的三步结构
只有当以下三点全部成立时,内部函数才真正构成闭包:
-
函数嵌套存在:内部函数(如
inner)完整定义在外部函数(如outer)的函数体内部,不是全局定义或动态生成 -
内部函数实际使用外部变量:不是简单地“看到”变量,而是表达式中直接读取或修改它(例如
print(x)、total += x),且该变量是外部函数的局部变量或参数(非全局) -
外部函数返回内部函数对象本身:返回的是
inner,不是inner()(后者是调用结果)。只有返回函数对象,才能让这个“记住环境”的能力被保留下来
引用关系不是显式建立,而是词法作用域决定的
Python 在定义 inner 的那一刻,就根据代码书写位置确定了它能访问哪些外部变量——这叫“词法作用域”。不需要 global 或 nonlocal 来建立引用关系;nonlocal 只在需要**修改**外部变量时才必需,读取则默认允许。
例如:
def make_multiplier(n):
def multiply(x): # ← 定义时就“锁定”了 n 所在的词法环境
return x * n # ← 这里引用 n,即构成引用关系
return multiply # ← 返回函数,不是结果运行 double = make_multiplier(2) 后,double 就是一个闭包,它内部已绑定了 n=2。
验证引用是否真正建立
可以通过函数对象的 __closure__ 属性查看。如果它是非空元组,每个元素是 cell 对象,就说明引用关系已构建成功:
-
double.__closure__→(<cell at int object>,)</cell> -
double.__closure__[0].cell_contents→2
若 __closure__ 为 None,说明没形成闭包——常见原因是内部函数根本没用到外部变量,或外部函数没返回内部函数。











