__slots__ 通过禁用 __dict__ 并用固定结构存储属性,将每个实例内存从约240字节降至仅指针大小(如16字节),显著降低大量对象的总体内存占用。
用 __slots__ 优化对象数量,核心是减少单个实例的内存占用,从而在创建大量对象时显著降低整体内存消耗。它不提升单次操作速度,但能让成千上万个实例更轻量、更紧凑。
__slots__ 能节省内存默认情况下,Python 对象通过 __dict__ 存储实例属性,这是一个动态字典,灵活但开销大(约 240 字节起步)。启用 __slots__ 后,Python 不再为每个实例创建 __dict__,而是将属性名预先声明为固定字段,底层用紧凑的 C 结构体存储——每个属性只占一个指针大小(通常 8 字节),且无哈希表管理成本。
__dict__ 和 __weakref__(除非显式加入)obj.x = 1 会报错)__slots__
在类定义中添加 __slots__ 类变量,值为字符串元组,列出所有允许的实例属性名:
class Point:
__slots__ = ('x', 'y')
def __init__(self, x, y):
self.x = x
self.y = y注意几点:
__slots__,子类也必须声明,否则子类会重新启用 __dict__,失去优化效果
'__weakref__' 加入 __slots__
__slots__(比如在 __init__ 中),它必须是类级常量__slots__
适合高频创建、生命周期短、结构固定的轻量对象场景:
不适合需要动态增删属性、频繁 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 = RegularPoi
nt(1, 2) p2 = SlottedPoint(1, 2)
print(getsizeof(p1)) # 通常 32–48 字节(含 dict) print(getsizeof(p2)) # 通常 16–32 字节(仅两个指针 + 对象头)
创建 10 万个实例时,内存差可能达数 MB —— 在内存敏感服务中很可观。