namedtuple 实例比普通 class 更省内存且更快,因其无 dict__、字段值平铺内存、访问走 c 层偏移计算;普通 class 需用 __slots 优化但牺牲动态性,而 namedtuple 天然支持 _asdict() 等方法且类对象更轻。

namedtuple 实例不带 __dict__,普通 class 默认有
普通 class 实例在创建时会自动分配一个 __dict__ 字典,用来动态存取任意属性。哪怕你只定义了两个字段,每个实例也要额外扛一个哈希表结构——光空 __dict__ 就占约 240 字节(Python 3.12),加上键值对存储开销,内存增长是线性的。
namedtuple 实例本质是 tuple 的子类,底层复用元组的紧凑内存布局:字段值直接平铺在连续内存块里,没有额外的字典、没有哈希表、没有属性查找缓存。它甚至不走 __setattr__ 那套逻辑,连属性名映射都编译期固化在类对象上。
结果就是:同样存 x 和 y 两个整数,Point(1, 2) 占用 ≈ 64 字节;而等价的普通 class 实例通常 ≥ 200 字节(不含 __dict__ 内容,仅结构本身)。
字段访问不触发字典查找,也不需要 __slots__ 手动优化
普通 class 要省内存,得显式加 __slots__ = ("x", "y") 关掉 __dict__。但一旦加了 __slots__,你就不能再动态赋新属性,也不能用 vars() 或 getattr(obj, key) 按字符串取值(除非自己实现),兼容性变差。
namedtuple 天然无 __dict__,且字段访问走的是 C 层级的固定偏移计算(类似 struct),比 __slots__ class 还快一点。你不需要做任何额外声明,它就“默认最优”。
常见误操作:class Point: __slots__ = ("x", "y") 确实能缩小内存,但如果你后续要支持 JSON 序列化、dataclasses.asdict() 或 IDE 动态补全字段,就得额外写 __getstate__、asdict() 方法——namedtuple 自带 _asdict() 和 _replace(),开箱即用。
类对象本身也更轻,尤其字段多时
namedtuple("BigConfig", ["field_" + str(i) for i in range(50)]) 生成的类,虽然字段多,但类体只是个轻量模板:没有方法代码体、没有 __init__ 函数对象、不维护 MRO 链表(除非继承)。它的 __new__ 是统一的 C 函数指针。
普通 class 定义 50 个字段,即使全用 __slots__,类对象本身也会因方法绑定、描述符、属性装饰器等膨胀。如果还用了 @dataclass,还会额外生成 __repr__、__eq__ 等函数对象——每个都是独立的 Python 对象,吃内存。
真正容易被忽略的一点:大量小对象场景下,内存节省主要不是来自单个实例少几十字节,而是避免了百万级 __dict__ 哈希表的碎片化分配。Python 的内存分配器对小 dict 很不友好,namedtuple 直接绕开了这整条链路。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











