sys.getsizeof仅测量对象自身结构体大小,不包含其引用的子对象内存;真实总内存需用pympler.asizeof或tracemalloc分析。

sys.getsizeof 不是“对象总内存”的测量函数,它只返回对象头 + 直接持有的数据结构的字节大小,对容器类、自定义类、嵌套引用几乎全部失效。
sys.getsizeof 对列表/字典等容器只算“箱子本身”,不算“箱子里的东西”
列表在内存中实际是一个指针数组(存储元素地址)加元数据(长度、容量、引用计数等)。sys.getsizeof 只计算这个指针数组和元数据的开销,完全忽略它指向的每个元素。
- 执行
sys.getsizeof([1, 2, 3])得到约 80–112 字节(取决于 Python 版本),这只是列表结构体大小;三个int对象各占约 28 字节,这部分不计入 - 执行
sys.getsizeof([[1,2], [3,4,5]])结果仍接近 80 字节——外层列表只存两个子列表的地址,子列表本身的大小、其内部整数的大小全被跳过 - 字典同理:
sys.getsizeof({'a': 1, 'b': 'x'})只反映哈希表桶数组和控制结构的尺寸,键、值对象的内存一概不统计
自定义类实例和 __slots__ 让 getsizeof 更不可信
对用户定义的类实例,sys.getsizeof 仅测量实例的 __dict__ 字典(或 __slots__ 元组)本身,对其字段引用的任何对象(比如一个 100MB 的 numpy.ndarray 或长字符串)完全视而不见。
快速生成专业的 Python 脚本和应用代码。一键创建完整项目结构,支持CLI、API、爬虫、Bot、Django等多种项目类型,包含完整的项目结构、配置文件、依赖管理、测试、README和文档。
- 有
__dict__的实例:返回值 ≈sys.getsizeof(obj.__dict__),即字典结构大小,而非字段值总和 - 用
__slots__的实例:返回值可能小得多(比如 48 字节),但这只是 slots 元组的开销,不代表它没引用大对象 - 方法、类定义、模块级变量等都不在测量范围内——
sys.getsizeof只看“这一个对象实例”的 C 层结构体
PyPy 和小对象驻留让跨环境测量彻底失效
CPython 的 sys.getsizeof 实现依赖底层 C 结构,而 PyPy 根本不支持它:sys.getsizeof(obj) 在 PyPy 上会直接抛 TypeError,除非你显式传入 default 参数(此时恒返回该默认值)。
- 小整数(-5 到 256)、短字符串常被驻留(interned),多个变量可能共享同一对象,但
sys.getsizeof对每个变量都单独计算,导致高估真实内存 - Python 3.3+ 对 Unicode 字符串做了紧凑存储优化,同样内容的字符串在 3.2 和 3.10 中测出的大小可能差一倍
- 内存对齐(如 8 字节边界填充)、解释器预分配策略也会影响实际物理占用,但
sys.getsizeof不体现这些
什么时候能用?怎么补救?
它唯一靠谱的使用场景是:对比同一类型、相似结构的**简单内置对象**在当前 CPython 环境下的结构体开销差异,比如空列表 vs 100 万元素列表的扩容行为,或不同长度字符串的 header 增长趋势。
- 要查真实总内存,用
pympler.asizeof.asizeof()—— 它递归遍历所有引用,累加全部可达对象 - 分析内存泄漏时,配合
tracemalloc比getsizeof有用十倍,它能定位到哪行代码分配了最多内存 - 别对
sys.getsizeof(type)或sys.getsizeof(int)抱期望——那测的是类对象本身,不是实例
真正容易被忽略的是:即使你严格按文档调用 sys.getsizeof,只要对象含引用(而几乎所有非叶子对象都含),结果就天然残缺。这不是 bug,是设计使然——它从一开始就没打算告诉你“程序总共用了多少内存”。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










