别再浪费内存了:Python __slots__ 机制深入解析

简介: Python中`__slots__`通过预定义属性名,避免使用`__dict__`存储,显著减少内存占用并提升访问速度。适用于需创建大量实例的场景,如数据处理、科学计算等,以牺牲动态添加属性为代价换取性能优化。

Python 对象的灵活性大家都知道,可以随时给对象添加属性:

class User:  
    pass  
u = User()  
u.name = "Alice"  
u.age = 30

但这种灵活性的代价也很大,每个普通 Python 对象都有个 __dict__ 字典来存储属性,对象一多内存开销就上来了,这时候 __slots__ 就派上用场。

slots 到底在干什么

__slots__ 让你提前声明类会用到哪些属性:

class User:  
    __slots__ = ["name", "age"]  
    def __init__(self, name, age):  
        self.name = name  
        self.age = age

这样做之后对象就不会再创建 __dict__ 了。属性存储变成静态的,查找和赋值都快了,尤其是创建大量实例时内存占用能降不少。

底层存储机制的差异

普通对象把每个属性当作 __dict__ 里的键值对访问属性就要做哈希查找。而用了 __slots__ 之后每个属性在内存里有个固定位置,访问变成了直接的数组索引操作省掉了字典查找的开销。

说白了就是把 Python 对象存储搞得像 C 的结构体一样紧凑。

内存能省多少

看个对比:

class Normal:  
    def __init__(self):  
        self.a = 1  
        self.b = 2  

class Slotted:  
    __slots__ = ["a", "b"]  
    def __init__(self):  
        self.a = 1  
        self.b = 2

如果要创建几百万个实例,用 __slots__ 的版本能少用 50-70% 的内存。

属性访问快主要是因为:省掉了字典查找、不用算哈希值、也没有额外的内存间接访问,属性访问时间一般能减少 20-40%。

使用限制

__slots__ 也不是完美的,有些限制得注意。

最明显的是不能随便加属性了:

u = User()  
u.address = "NYC"  # ❌ AttributeError

继承的时候也麻烦,子类得定义自己的 __slots__,而且混用带slots和不带slots的类要小心。多重继承更复杂只有slots名不冲突才行。

另外默认不支持弱引用,要用的话得在 __slots__ 里显式加上 __weakref__

什么场景适合用

几个典型场景:处理大数据集时有几百万个对象;科学计算里的轻量数据结构、游戏引擎里的实体和粒子系统等等,总之就是那些对内存和速度敏感的地方。

一些实用技巧

配合类型提示用能让代码更清晰。可以和 @property 装饰器结合,该灵活的地方还是保持灵活。空类直接用 __slots__ = () 把开销降到最低。

总结

__slots__ 就是让你用灵活性换内存效率和更快的属性访问。对于高性能场景来说这是个必须掌握的优化手段。

就算项目暂时不缺内存,理解 __slots__ 本身也很有价值。它能让你明白 Python 对象是怎么存属性的、属性查找为什么有成本、Python 在灵活性和效率之间怎么权衡。

这些知识对系统设计、性能调优、排查问题都有帮助。

https://avoid.overfit.cn/post/c18314c17e0047358cb13c0a990067ae
作者:Elshad Karimov

目录
相关文章
|
8月前
|
SQL 分布式计算 大数据
别让大数据任务“互相等着死” ——聊聊任务依赖与 DAG 设计的江湖规矩
别让大数据任务“互相等着死” ——聊聊任务依赖与 DAG 设计的江湖规矩
396 6
|
Python
Python中遇到奇怪的错误ValueError: bad marshal data
不是代码出的问题,是*.pyc文件被改动了。解决方法,删除所有*.pyc文件再运行
5516 0
|
Python
Python 中__new__方法详解及使用
__new__ 是 Python 中用于创建类实例的静态方法,在实例化对象时优先于 __init__ 执行。它定义在基础类 object 中,需传递 cls 参数(表示当前类)。__new__ 可决定是否使用 __init__ 方法或返回其他对象作为实例。特性包括:1) 在实例化前调用;2) 始终为静态方法。示例中展示了其用法及 Python2 和 Python3 的差异,强调了参数处理的不同。
629 10
|
人工智能 安全 网络安全
2025攻防演习回顾,AI赋能下的网络安全新格局
网络安全实战攻防演习历经9年发展,已成为检验安全体系、洞察威胁趋势的重要手段。攻击呈现实战化、体系化特征,APT、0day、勒索攻击等手段升级,AI、大数据等新技术带来新风险。攻击入口多元化、工具智能化、API成重点目标,“AI+人工”协同攻击加剧威胁。面对挑战,企业需构建纵深防御体系,从被动防御转向主动对抗。瑞数信息通过动态安全技术与AI融合,实现0day防护、漏扫干扰、勒索应急等能力,打造WAAP超融合平台,助力关键基础设施构建智能、协同、前瞻的主动防御体系。
929 1
|
数据挖掘 测试技术 定位技术
《深入剖析:Python自动化测试框架之unittest与pytest》
unittest 和 pytest 是 Python 自动化测试领域的两大利器。unittest 作为标准库的一部分,像一位严谨的“老工匠”,以面向对象的方式提供标准化、可靠的测试基础,适合初学者和小型项目。其 TestCase 类为核心,setup/teardown 方法确保测试独立性。 pytest 则如一位灵活的“艺术家”,以简洁自由的风格和强大功能脱颖而出。它支持参数化测试、灵活的 fixture 机制,并拥有丰富的插件生态,适合复杂场景和大型项目。两者各有优劣,选择需根据项目需求权衡:unittest 稳定兼容,pytest 灵活高效。掌握二者特性,可助力开发者构建高质量测试框架。
666 12
|
7月前
|
安全 网络安全 开发工具
解决 Host key verification failed 报错的三种方法(含 SSH 安全建议)
本文由喵喵侠撰写,详解Git提交时常见报错“Host key verification failed”的成因与解决方案。当SSH密钥变更或服务器重装系统时,本地记录的主机密钥会失效,导致连接被拒。文章提供三种解决方法:使用`ssh-keygen -R`删除旧密钥、手动编辑`known_hosts`文件,或临时禁用严格检查(不推荐生产环境)。同时强调安全建议:确认服务器状态、核对密钥指纹、启用`VerifyHostKeyDNS`防范中间人攻击。帮助开发者快速定位问题,保障代码提交顺畅。
2927 0
|
Linux 网络安全 数据安全/隐私保护
使用Linux系统的mount命令挂载远程服务器的文件夹。
如此一来,你就完成了一次从你的Linux发车站到远程服务器文件夹的有趣旅行。在这个技术之旅中,你既探索了新地方,也学到了如何桥接不同系统之间的距离。
2182 21
|
SQL 安全 关系型数据库
【MySQL基础篇】事务(事务操作、事务四大特性、并发事务问题、事务隔离级别)
事务是MySQL中一组不可分割的操作集合,确保所有操作要么全部成功,要么全部失败。本文利用SQL演示并总结了事务操作、事务四大特性、并发事务问题、事务隔离级别。
6099 56
【MySQL基础篇】事务(事务操作、事务四大特性、并发事务问题、事务隔离级别)
成功解决:snippet设置的开机自启没有效果
这篇文章分享了解决Snipaste软件设置开机自启无效的问题,通过将Snipaste的快捷方式放入Windows的开机启动目录来实现开机自动运行。
成功解决:snippet设置的开机自启没有效果

热门文章

最新文章