




用 __slots__ 可将实例内存压缩至原来的1/3~1/5,因禁用__dict__和__weakref__,属性转为固定偏移存储;需显式声明属性名,父类启用则子类也须定义,否则优化失效。
__slots__ 禁用动态属性能省多少内存?默认情况下,Python 每个实例都带一个 __dict__ 字典来存属性,哪怕只存 2–3 个字段,也要额外占用 ~240 字节。上万对象时,这部分开销就非常可观。
加 __slots__ 后,实例不再有 __dict__ 和 __weakref__,属性直接映射到预分配的固定偏移量,内存可压缩到原来的 1/3~1/5。
__slots__ = ('id', 'name', 'score')
AttributeError: 'X' object has no attri
bute 'xxx'
__slots__,子类也得定义,否则父类的优化会被子类的 __dict__ 覆盖'__dict__' 在 slots 元组里,但那就失去大部分优化效果__new__ + 缓存)适合哪些场景?不是所有对象都适合池化。只有满足「创建开销大 + 生命周期短 + 实例可复用」三个条件时才值得做,比如网络连接、线程本地配置、坐标点(若业务中大量重复构造相同值)。
常见误用是拿它优化普通数据容器(如 User),反而因哈希/查找引入额外开销,且容易引发状态残留 bug。
weakref.WeakValueDictionary 存缓存,避免对象永久驻留__new__ 时,先查池、命中则跳过 super().__new__,未命中再创建并存入池__init__ 或复用前清空字段),否则上次使用残留的数据会污染下次调用threading.Lock),但锁本身可能成为瓶颈,建议按 key 分片加锁array.array 和 struct.pack 替代对象列表真能提速?当你要存的是同构数值数据(比如十万条 (x: float, y: float, z: float)),用对象列表是典型的空间浪费:每个 Point 实例至少 48 字节 + 3 × 24 字节浮点对象引用 + 冗余类型信息。
换成 array.array('d', [...]) 或 struct.pack('ddd', x, y, z) 打包成二进制块,内存直接降到 1/5 以内,且 CPU 缓存友好,遍历速度通常快 3–10 倍。
array.array 只支持基础类型('i', 'd', 'B' 等),不支持嵌套或混合类型struct 需自己管理偏移和解包逻辑,适合固定结构+批量读写;array 更适合单值追加和随机访问numpy.ndarray —— 它底层也是紧凑内存布局,还带向量化操作__del__ 和弱回调不适合内存敏感场景?很多人想靠 __del__ 主动归还资源或清理缓存,但这不可靠:CPython 中它依赖引用计数归零触发,PyPy/其他实现甚至不保证调用时机;循环引用下更可能永不触发。
弱引用回调(weakref.ref(obj, callback))看似优雅,但 callback 执行时机不确定,且每次注册都会产生额外对象(弱引用本身也有开销),在高频创建/销毁场景下反而增加 GC 压力。
with)、手动 .close()、或把对象生命周期绑定到某个明确的 owner 上weakref.finalize(比 __del__ 更可靠),但仍要避免在 finalize 里做耗时或依赖其他对象的操作内存优化不是堆技巧,而是对数据建模方式的重新审视。一个 __slots__ 能省几百 MB,但若本该用 array 存的数据硬套 class,再怎么调参也救不回来。