Python基础教程(三十五)使用__slots__:内存杀手锏:Python的__slots__魔法

当百万级对象吞噬内存时,__slots__如同Python性能优化的暗黑艺术,用空间换时间的博弈颠覆传统对象模型。


内存吞噬者:动态字典的原罪

普通Python类实例通过__dict__字典动态存储属性:

class User:
    pass

u = User()
u.name = "Alice"  # 动态写入__dict__

每个实例需额外存储字典数据结构(约240字节基础开销),百万实例即浪费240MB内存。

__slots__的魔法阵

声明固定属性列表,替换动态字典:

class SlotUser:
    __slots__ = ('name', 'age')  # 预定义属性白名单

su = SlotUser()
su.name = "Bob"   # 直接写入固定内存槽
su.email = "x@x"  # 触发AttributeError!
  • 内存优化:消除__dict____weakref__(若未显式声明)开销
  • 访问加速:数组索引访问 vs 字典哈希查找

性能实测:数据不说谎

import sys

class DictClass: pass
class SlotClass: __slots__ = ('x',)

dict_objs = [DictClass() for _ in range(100000)]
slot_objs = [SlotClass() for _ in range(100000)]

print(sys.getsizeof(dict_objs))  # ≈22.4MB 
print(sys.getsizeof(slot_objs))  # ≈12.5MB (节省44%)

继承链中的暗雷

class Parent:
    __slots__ = ('a',)

class Child(Parent):
    __slots__ = ('b',)  # 合并父类slots:实际为('a','b')

class GrandChild(Child):
    __slots__ = Parent.__slots__ + Child.__slots__  # 显式合并最佳实践
  • 子类未声明__slots__时继承父类但获得__dict__
  • 多继承需手动合并所有父类__slots__

适用场景:性能与灵活的抉择

场景

推荐使用

不推荐使用

高频创建小对象

需动态添加属性

❌ (丧失灵活性)

内存敏感型应用

复杂继承结构

⚠️ 谨慎

警示__slots__不是银弹。在Django等ORM框架中滥用会破坏动态查询,而在需要weakrefpickle的场景需显式声明__weakref__。下个问题:当__slots__遇见元类编程时,会碰撞出怎样的火花?

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

值引力

持续创作,多谢支持!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值