__slots__能省几十到上百字节,因为禁用__dict__字典(约240字节开销)而改用紧凑数组存储属性,每个字段仅占8字节指针并采用偏移寻址。

__slots__ 为什么能省下几十到上百字节?
因为 Python 默认给每个实例配一个 __dict__ 字典,哪怕只存一个 int,这个字典在 64 位 CPython 中就占约 240 字节——它包含哈希表头、空桶数组、引用计数等“基础税”。而 __slots__ 直接禁用 __dict__,改用紧凑数组存储属性值,每个字段只占一个指针大小(通常 8 字节),且访问走偏移寻址,跳过哈希计算。
什么时候省内存效果最明显?
不是所有类都值得加 __slots__,关键看场景:
- 对象数量 ≥ 1 万,且结构固定(如坐标
Point、特征向量FeatureRow、事件消息IoTEvent) - 每个实例只存 2–5 个字段,但
__dict__开销占比奇高(实测 10 万个Point实例:普通类约 24 MB,加__slots__后约 14 MB) - 部署在内存受限环境(边缘设备、Serverless 函数、容器化微服务)
- 不用
__dict__动态赋值、不依赖第三方库的运行时属性注入(如 Django ORM、某些序列化工具)
常见踩坑点:为什么加了 __slots__ 还没省内存?
失效往往不是语法错,而是隐性条件不满足:
- 子类没声明自己的
__slots__→ 父类的__slots__白写,__dict__照常生成 - 继承链里任一父类带
__dict__(比如继承了Exception或某些第三方基类)→ 整个继承链退化 -
__slots__ = 'x'写成单字符串 → 被当成('x',)的误写,实际拆成('x',)是对的,但__slots__ = 'xy'会被拆成('x', 'y'),极易出错 - 漏写私有字段(如
_cache、__internal)→ 运行时报AttributeError,但不会报内存问题,容易被忽略
@dataclass(slots=True) 和手写 __slots__ 有什么区别?
Python 3.10+ 的 @dataclass(slots=True) 等价于手写 __slots__,但要注意:
立即学习“Python免费学习笔记(深入)”;
- 它自动生成
__init__和__repr__,省事;但若父类没__slots__,slots=True无效 - 不能像手写那样灵活控制(比如显式加入
'__weakref__'支持弱引用) - 调试时看不到
__dict__,vars(obj)报错,得用obj.__slots__配合getattr查字段
真正难的不是加一行 __slots__,而是确认整个继承链干净、所有可能赋值的字段名都列全、且上下游工具链不依赖 __dict__。漏掉任意一环,内存账就算不准。


















