Python 对象模型与内存
一切皆对象:对象有身份类型值;CPython 以引用计数为主回收,辅以循环 GC。
#type / concept
#status / growing
#tech / dev
#resource / python
#tech / lang / python
[!info] 关联笔记
Python 对象模型与内存
这个概念为什么出现
id、共享、循环引用、__slots__ 内存——都依赖“对象头 + 引用”这一层。本篇给 CPython 直觉,并标明实现边界。
[!abstract] 一句话理解 值以堆上对象存在,名字持有引用;CPython 主要靠引用计数立刻回收,循环引用交给周期 GC。
最小可观察示例
场景:观察对象身份与引用变化
# object_identity_demo.py
# 业务意图:展示同一 list 多引用与 is。
# 教学点:对象身份;引用共享。
def main() -> None:
a = ["order"]
b = a
print("id equal?", id(a) == id(b), "is?", a is b)
b.append("line")
print(a)
if __name__ == "__main__":
main()
建议运行:
python object_identity_demo.py
期望输出:
id equal? True is? True
['order', 'line']
结合场景再看三个关注点
- 身份稳定于对象生命周期。
- 共享写可见。
- 引用计数细节用工具观察,不靠猜。
核心概念与准确模型
- 每个对象:身份、类型、值
- CPython:
PyObject头含引用计数等 - 小对象分配器(pymalloc)等实现优化
__slots__减少实例 dict
边界情况与反直觉行为
- intern 使某些字面量身份重合
- 循环引用 单靠计数不够
- 原生扩展 内存另一套
常见误区
[!warning] 常见误区:id 当序列号持久化 错误理解:id 全局永久唯一可存库。
正确模型:只在进程内生命周期有意义。
工程实践
- 大对象及时释放引用
- 内存问题用 tracemalloc/采样
- 热路径对象池要非常谨慎
本节总结
对象模型连接语言使用与运行时成本。下一篇专讲 GC 与循环。
自测题
- 名字删除是否立即释放对象?
- 为什么 id 不适合持久化?
参考答案
- 引用计数归零才可释放(循环另论)。
- 可复用且仅进程内有效。
延伸阅读与资料来源
| 资料 | 类型 | 支撑内容 |
|---|---|---|
| Data model | 规范 | 对象 |
| gc module | 文档 | 回收接口 |