👉 项目官网:https://www.python-office.com/ 👈
👉 本开源项目的交流群 👈
more >>在 Python 的世界里,“灵活性”是其核心哲学之一。默认情况下,Python 对象的实例属性都存储在一个动态的字典 __dict__
中,这使得我们可以随时随地、随心所欲地为对象添加新的属性。然而,这种灵活性并非没有代价,它带来了显著的内存开销和相对缓慢的属性访问速度。
当你需要创建成千上万个对象实例时(例如在科学计算、Web 框架处理大量请求、游戏开发中处理大量实体时),这种开销就会变得不可忽视。这时,__slots__
这个强大的魔术方法就派上了用场。它通过一种声明式的机制,在灵活性和性能之间提供了一个高效的权衡。
本文将深入探讨 __slots__
的工作原理、使用方法、性能优势以及需要注意的陷阱。
__slots__
是什么?__slots__
是一个类变量,它允许开发者显式地声明一个类所允许拥有的实例属性名称。其语法非常简单:
1 | class MyClass: |
通过这行声明,你告诉 Python 解释器:MyClass
的实例只能拥有 attr1
, attr2
, attr3
这三个属性。解释器会据此进行内存分配和属性访问管理,而不是使用默认的 __dict__
字典。
__slots__
行为__dict__
的动态属性在没有 __slots__
的普通类中,每个实例都拥有一个 __dict__
字典来存储其所有属性。
1 | class RegularUser: |
优点:极高的灵活性。
缺点:
__slots__
行为:基于描述符的固定属性使用 __slots__
后,Python 不再为每个实例创建 __dict__
,而是为整个类创建一个描述符 (Descriptor),并为每个实例在 C 层分配一个固定的、紧凑的数组来存储 __slots__
中声明的属性。
1 | class SlotsUser: |
优点:
__slots__
中声明的属性。__dict__
**:一些序列化或调试工具可能依赖于 __dict__
的存在。内存节省主要来自两个方面:
移除了 __dict__
**:一个空的字典在 64 位 Python 解释器下大约占用 240 字节。对于属性数量很少但实例数量极多的类(例如坐标点 Point(x, y)
),节省的内存是巨量的。内存节省的不是属性值的空间,而是存储这些属性所用的数据结构**的空间。
紧凑的内存布局:Python 解释器会为 __slots__
的实例预分配一块连续的内存空间,每个属性在其中的偏移量是固定的。这比使用字典(需要存储哈希表、键和值指针等)要高效得多。
让我们用一个简单的例子来量化这种节省:
1 | import sys |
输出可能会类似于(具体数字因Python版本和系统而异):
1 | Regular instance size: 56 bytes |
单个实例节省了 8 字节。看起来不多?让我们放大规模:
1 | # 创建一百万个实例,估算总内存消耗 |
输出可能类似于:
1 | Estimated memory for 1,000,000 Regular instances: 53.41 MB |
节省了超过 7MB 的内存! 对于属性更少的类,比例会更加惊人。
__slots__
1 | class Vector2D: |
使用 __slots__
时,继承链需要小心处理。
__slots__
**:子类使用 __slots__
后,实例仍然会有 __dict__
(除非子类的 __slots__
也阻止了它),因为需要容纳父类的潜在动态属性。这会削弱 __slots__
的效果。__slots__
**:子类也需要定义自己的 __slots__
,它应该包含**父类的 __slots__
。1 | class Base: |
如果需要对你的类实例使用弱引用 (weakref
),你需要将 '__weakref__'
explicitly 加入到 __slots__
中。
1 | class WeakRefableSlots: |
除了内存,__slots__
还能提升属性访问速度。
1 | import timeit |
输出可能显示 __slots__
的属性访问有 20%-40% 的速度提升。
__slots__
?pickle
)可以正常工作,但某些深度依赖 __dict__
或 __dir__
的库或调试工具可能会出现问题。__slots__
。__slots__
是自找麻烦。“明确优于隐晦”,只在真正需要时使用。__slots__
是 Python 提供给开发者的一个强大工具,它在牺牲一部分动态灵活性的前提下,换来了显著的内存节省和一定的性能提升。它完美体现了 Python “实用主义” 的哲学:提供机制,让开发者根据实际情况决定策略。
在开发大型应用、处理海量数据或编写底层基础构件时,善用 __slots__
可以有效地优化程序资源消耗。然而,就像所有优化技巧一样,它的首要原则是 “不要过早优化” 。首先保证代码的正确性和清晰度,然后在性能分析工具的指导下,有针对性地使用 __slots__
来解决实际存在的内存或性能瓶颈。
大家学习 或 使用代码过程中,有任何问题,都可以加入读者群交流哟~👇
tag:
缺失模块。
1、请确保node版本大于6.2
2、在博客根目录(注意不是yilia根目录)执行以下命令:
npm i hexo-generator-json-content --save
3、在根目录_config.yml里添加配置:
jsonContent: meta: false pages: false posts: title: true date: true path: true text: false raw: false content: false slug: false updated: false comments: false link: false permalink: false excerpt: false categories: false tags: true