惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Simon Willison's Weblog
Simon Willison's Weblog
T
Threatpost
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Spread Privacy
Spread Privacy
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Engineering at Meta
Engineering at Meta
T
Tenable Blog
C
Cisco Blogs
T
The Blog of Author Tim Ferriss
NISL@THU
NISL@THU
T
Threat Research - Cisco Blogs
T
The Exploit Database - CXSecurity.com
P
Privacy & Cybersecurity Law Blog
Recent Commits to openclaw:main
Recent Commits to openclaw:main
S
Secure Thoughts
N
News and Events Feed by Topic
Google DeepMind News
Google DeepMind News
博客园 - 三生石上(FineUI控件)
Microsoft Azure Blog
Microsoft Azure Blog
月光博客
月光博客
H
Hacker News: Front Page
I
InfoQ
L
LangChain Blog
Security Latest
Security Latest
The Cloudflare Blog
Forbes - Security
Forbes - Security
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Stack Overflow Blog
Stack Overflow Blog
TaoSecurity Blog
TaoSecurity Blog
量子位
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
V
Visual Studio Blog
Scott Helme
Scott Helme
爱范儿
爱范儿
A
Arctic Wolf
F
Full Disclosure
酷 壳 – CoolShell
酷 壳 – CoolShell
Schneier on Security
Schneier on Security
N
News and Events Feed by Topic
C
CXSECURITY Database RSS Feed - CXSecurity.com
L
LINUX DO - 最新话题
V2EX - 技术
V2EX - 技术
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
人人都是产品经理
人人都是产品经理
The Hacker News
The Hacker News
Hugging Face - Blog
Hugging Face - Blog
Security Archives - TechRepublic
Security Archives - TechRepublic
Know Your Adversary
Know Your Adversary
Application and Cybersecurity Blog
Application and Cybersecurity Blog

博客园 - 悠哉大斌

AI Agent 安全沙箱技术对比:E2B、Cube Sandbox 与 Docker Sandboxes linux 升级 claude code的坑 debian(WSL) apt 代理配置 linux内核之Namespaces、Cgroups、Capabilities、Seccomp和Landlock 大语言模型推理中的隐藏瓶颈及其解决方法 Docker Sandboxes 技术是什么,和docker容器有什么区别 什么是 Docker Agent以及一个Docker Agent示例 windows wsl 安装 Temurin® JDK claude Code 和 codex 作为编程代理,前者使用typescript开发,后者使用rust,他们的决策依据是什么 Java 并发编程发展史与 java.util.concurrent 全景解析 LLM 真的改变了编码风格吗? 如果人工智能会犯错且不精确,为什么它正在改变世界? Python 的协程模型和 JavaScript 的 async/await python 的 dunder name和 sunder name 基于nodejs设计REST API的知名开源框架 windows上使用node-oracledb Thick 模式连接 Oracle 11g Claude Code CLI连接 DeepSeek V4模型后调用报400错误 python里对象(object)到底是什么 Python 泛型演变史 Python 类型别名的演变 Python 类型提示的演变史 PEP 593 新增的Annotated 类型 Alibaba AgentScope 和 microsoft agent framework 详细对比分析 spring AI Alibaba Agent Framework 和 agentscope有什么区别和联系 AI Agent协作模式以及主流开源框架对协作模式的支持 Tailscale 是如何接管 DNS 的? Agent = Model + Harness 使用rust编写typescript编译器的难点在什么地方,哪些数据结构是rust不擅长的? TypeScript/JavaScript 中的异步迭代语句 js中的生成器函数 Tailscale Serve and Funnel openclaw gateway的网络绑定模式 websocket协议和http协议有何依赖关系? MCP通信的双方是谁? claude code MCP 安装范围 如何在wsl2环境下给claude code cli 配置 playwright-mcp wsl的网络模式有哪几种,有哪些区别? AI Agent memory是什么? ai agent skills是什么? Go测试生态系统工具与最佳实践深度调研(聚焦认证授权系统) 线性代数中常见矩阵类型的概念关系思维导图 三种主流授权策略
python闭包和function.__closure__特殊属性
悠哉大斌 · 2026-05-13 · via 博客园 - 悠哉大斌

function.__closure__ 是 Python 函数对象上的一个特殊属性,用来保存 闭包(closure)捕获的自由变量

它的值通常是:

  • None
  • 或一个由 cell 对象组成的元组

它和 function.__code__.co_freevars 配合使用。


一、什么是闭包(closure)

先看例子:

def outer():
    x = 10

    def inner():
        return x

    return inner

这里:

f = outer()

此时:

f()
# 10

问题来了:

  • outer() 已经执行结束
  • 按理说局部变量 x 应该销毁
  • 为什么 inner() 还能访问 x

因为:

Python 把 x “封”进了闭包里。

这个闭包就保存在:

f.__closure__

二、closure 长什么样

继续:

f = outer()

print(f.__closure__)

结果类似:

(<cell at 0x000001F2...: int object at ...>,)

这是:

  • 一个 tuple
  • 里面是 cell 对象
  • 每个 cell 保存一个被捕获的变量

查看内容:

print(f.__closure__[0].cell_contents)

输出:

10

三、和 co_freevars 的关系

看:

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 对象是什么

闭包变量不是直接保存值。

而是:

变量名 -> 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

七、没有闭包时 closure 是 None

def foo():
    return 123

print(foo.__closure__)

输出:

None

因为:

没有捕获外部变量。


八、为什么闭包重要

很多 Python 特性依赖闭包:

  • 装饰器
  • 回调
  • 工厂函数
  • 柯里化
  • 延迟绑定
  • FastAPI dependency
  • functools.partial 的一些思想

例如装饰器:

def log(func):

    def wrapper(*args, **kwargs):
        print("calling")
        return func(*args, **kwargs)

    return wrapper

这里:

wrapper

捕获了:

func

所以:

wrapper.__closure__

里就有 func


九、深入理解:为什么 Python 要设计 closure

核心原因:

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,主要由解释器自动创建