






















function.__closure__ 是 Python 函数对象上的一个特殊属性,用来保存 闭包(closure)捕获的自由变量。
它的值通常是:
Nonecell 对象组成的元组它和 function.__code__.co_freevars 配合使用。
先看例子:
def outer():
x = 10
def inner():
return x
return inner
这里:
f = outer()
此时:
f()
# 10
问题来了:
outer() 已经执行结束x 应该销毁inner() 还能访问 x?因为:
Python 把 x “封”进了闭包里。
这个闭包就保存在:
f.__closure__
继续:
f = outer()
print(f.__closure__)
结果类似:
(<cell at 0x000001F2...: int object at ...>,)
这是:
查看内容:
print(f.__closure__[0].cell_contents)
输出:
10
看:
print(f.__code__.co_freevars)
输出:
('x',)
表示:
函数依赖一个自由变量:
x
而:
f.__closure__
保存的是:
x 对应的实际值
对应关系:
| 属性 | 含义 |
|---|---|
co_freevars |
自由变量名字 |
__closure__ |
自由变量实际 cell |
def outer():
x = 10
y = 20
def inner():
return x + y
return inner
f = outer()
查看:
print(f.__code__.co_freevars)
输出:
('x', 'y')
查看:
for cell in f.__closure__:
print(cell.cell_contents)
输出:
10
20
闭包变量不是直接保存值。
而是:
变量名 -> cell -> 真正对象
原因是:
闭包里的变量可能被修改。
例如:
def counter():
n = 0
def inc():
nonlocal n
n += 1
return n
return inc
这里:
c = counter()
c() # 1
c() # 2
c() # 3
因为:
多个调用共享同一个 cell。
这个例子:
def outer():
x = 10
def inner():
return x
return inner
可以理解为:
inner function
│
├── __code__
│ └── co_freevars = ('x',)
│
└── __closure__
└── cell
└── 10
def foo():
return 123
print(foo.__closure__)
输出:
None
因为:
没有捕获外部变量。
很多 Python 特性依赖闭包:
例如装饰器:
def log(func):
def wrapper(*args, **kwargs):
print("calling")
return func(*args, **kwargs)
return wrapper
这里:
wrapper
捕获了:
func
所以:
wrapper.__closure__
里就有 func。
核心原因:
Python 函数是“一等对象”。
函数:
closure 本质是:
函数 + 创建时环境
这也是函数式编程的重要基础。
理论上:
cell.cell_contents
可读。
但通常不建议直接改。
因为这是 CPython 内部机制的一部分。
funcs = []
for i in range(3):
funcs.append(lambda: i)
for f in funcs:
print(f())
输出:
2
2
2
原因:
lambda 捕获的是:
同一个 cell
不是当时的值。
所以循环结束后:
i == 2
全部都看到 2。
解决:
funcs.append(lambda i=i: i)
这里利用默认参数提前绑定值。
function.__closure__:
用于保存:
函数捕获的外部变量
核心特点:
| 特性 | 说明 |
|---|---|
| 类型 | tuple 或 None |
| 内容 | cell 对象 |
| 配套属性 | co_freevars |
| 作用 | 实现闭包 |
| 本质 | 保存函数创建时的环境 |
可以把 closure 理解为:
函数对象携带的“外部作用域快照”
但它保存的不是简单值拷贝,而是:
共享 cell 引用
注意:cell 是 CPython 里的一个内置底层对象类型,专门用于实现闭包(closure)。但它:
1,不属于我们日常能直接构造的公开内置类型
2,没有 cell() 这种构造函数
3,主要由解释器自动创建
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。