__slots__能显著减少内存占用,因禁用每个实例的__dict__字典(约240字节开销),改用预分配的固定偏移数组存储属性,内存可压缩至原大小的1/3~1/2,但仅在大量小实例(如百万级模型对象)时效果显著。

为什么 __slots__ 能减少内存占用?
Python 默认为每个实例动态分配一个 __dict__ 来存储属性,哪怕只存几个字段,也要额外开销 ~240 字节(CPython 3.12)。启用 __slots__ 后,实例不再创建 __dict__,属性直接映射到预分配的固定偏移位置,内存可压缩至原大小的 1/3~1/2。
但注意:这仅对**大量小实例**(如模型对象、事件数据、树节点)有效;单个实例节省几十字节,百万级才见真效果。
怎么正确声明 __slots__?
在类定义中直接赋值一个字符串元组,列出所有允许的实例属性名:
class Point:
__slots__ = ('x', 'y')
<pre class='brush:python;toolbar:false;'>def __init__(self, x, y):
self.x = x
self.y = y</pre>常见错误:
立即学习“Python免费学习笔记(深入)”;
- 写成列表或字符串(
__slots__ = ['x','y']或__slots__ = 'x y')→ 运行时报TypeError: '__slots__' must be a string or an iterable of strings - 漏写父类已用的属性 → 子类实例仍会生成
__dict__,完全失效 - 混用
__slots__和__dict__→ 显式定义__dict__在__slots__中才能恢复动态属性(不推荐)
继承时 __slots__ 怎么协同?
子类默认不继承父类的 __slots__;如果父类用了,子类也必须显式声明,否则会自动获得 __dict__,前功尽弃:
class Shape:
__slots__ = ('color',)
<p>class Circle(Shape):
<strong>slots</strong> = ('radius',) # 必须写!否则 Circle 实例有 <strong>dict</strong></p><h1>错误示例:没声明 <strong>slots</strong></h1><p>class BadCircle(Shape):
pass # → 实例带 <strong>dict</strong>,color 和未来属性都走字典若需兼容动态属性,可在 __slots__ 中包含 '__dict__',但这就失去内存优势了——只在极少数过渡场景用。
哪些情况不能用或不该用 __slots__?
__slots__ 是有代价的约束,不是银弹:
- 无法给实例动态添加属性(
obj.z = 1→AttributeError) - 不能被
weakref引用,除非显式加入'__weakref__'到__slots__ - 与某些依赖
__dict__的库冲突(如dataclasses.asdict()、json.dumps(obj)直接失败) - 调试时 inspect 属性变麻烦(
vars(obj)返回空)
真正要压内存时,得连序列化、反射、动态扩展一起重新设计——光加 __slots__ 只是第一步,后面全是取舍。


















