__slots__ 通过禁用 __dict__ 并用固定结构存储属性,将每个实例内存从约240字节降至仅指针大小(如16字节),显著降低大量对象的总体内存占用。

用 __slots__ 优化对象数量,核心是减少单个实例的内存占用,从而在创建大量对象时显著降低整体内存消耗。它不提升单次操作速度,但能让成千上万个实例更轻量、更紧凑。
为什么 __slots__ 能节省内存
默认情况下,Python 对象通过 __dict__ 存储实例属性,这是一个动态字典,灵活但开销大(约 240 字节起步)。启用 __slots__ 后,Python 不再为每个实例创建 __dict__,而是将属性名预先声明为固定字段,底层用紧凑的 C 结构体存储——每个属性只占一个指针大小(通常 8 字节),且无哈希表管理成本。
- 没有
__dict__和__weakref__(除非显式加入) - 属性访问仍为 O(1),且略快于字典查找
- 类定义时即锁定属性名,运行时无法新增属性(如
obj.x = 1会报错)
怎么正确使用 __slots__
在类定义中添加 __slots__ 类变量,值为字符串元组,列出所有允许的实例属性名:
class Point:
__slots__ = ('x', 'y')
def __init__(self, x, y):
self.x = x
self.y = y注意几点:
立即学习“Python免费学习笔记(深入)”;
- 父类用了
__slots__,子类也必须声明,否则子类会重新启用__dict__,失去优化效果 - 若需支持弱引用,显式把
'__weakref__'加入__slots__ - 不能直接赋值给
__slots__(比如在__init__中),它必须是类级常量 - 类属性、方法、类变量不受影响,照常工作
什么时候该用 __slots__
适合高频创建、生命周期短、结构固定的轻量对象场景:
- 数据容器类:如坐标点、RGB 值、CSV 行解析结果
- ORM 模型中的实体(尤其批量查询返回数千条记录时)
- 游戏或仿真中成千上万个粒子、节点、状态对象
不适合需要动态增删属性、频繁 monkey patch、或依赖 __dict__ 的框架(如某些序列化库、调试工具)。
验证内存节省效果
可以用 sys.getsizeof() 粗略对比(注意:它不包含所引用对象的内存,仅实例本身):
from sys import getsizeofclass RegularPoint: def init(self, x, y): self.x = x self.y = y
class SlottedPoint: slots = ('x', 'y') def init(self, x, y): self.x = x self.y = y
p1 = RegularPoint(1, 2) p2 = SlottedPoint(1, 2)
print(getsizeof(p1)) # 通常 32–48 字节(含 dict) print(getsizeof(p2)) # 通常 16–32 字节(仅两个指针 + 对象头)
创建 10 万个实例时,内存差可能达数 MB —— 在内存敏感服务中很可观。










