__slots__用于限制实例属性并节省内存,通过固定结构替代__dict__存储,禁止动态添加属性除非包含'__dict__',仅影响实例属性不影响类属性和方法,继承时子类需声明slots以添加属性,多继承中避免多个父类有非空slots。

Python 3 中使用 __slots__ 是一个常见但容易引发疑问的特性。它用于限制类实例的属性,并优化内存使用。以下是开发者在使用过程中常遇到的几个问题及其解释。
1. __slots__ 是什么,为什么要用它?
__slots__ 是一个类变量,用来显式声明实例中允许存在的属性名称。定义了 __slots__ 后,该类的实例将不再使用 __dict__ 存储属性,而是通过固定大小的结构存储,从而节省内存。
主要用途包括:
- 减少内存占用,尤其在创建大量实例时效果明显
- 防止动态添加新属性,提高程序安全性与可维护性
- 加快属性访问速度(微小提升)
2. 为什么实例不能再动态添加属性?
当类定义了 __slots__,Python 不再为每个实例创建 __dict__。由于没有字典来存放新的属性,尝试赋值不存在于 slots 中的属性会触发 AttributeError。
立即学习“Python免费学习笔记(深入)”;
例如:
class Point:
__slots__ = ['x', 'y']
p = Point()
p.x = 10
p.z = 20 # 报错:AttributeError: 'Point' object has no attribute 'z'
如果确实需要动态属性,不要使用 __slots__,或在 slots 中包含 '__dict__'。
3. slots 中包含 '__dict__' 会怎样?
如果在 __slots__ 列表中加入字符串 '__dict__',实例将恢复支持动态添加属性,因为此时会创建一个 __dict__ 来存储额外属性。
示例:
class Flexible:
__slots__ = ['x', '__dict__']
f = Flexible()
f.x = 1
f.y = 2 # 允许,y 存入 dict
这样做会部分抵消 slots 的内存优势,但在需要灵活性时是折中方案。
4. slots 是否影响类属性或方法?
不影响。slots 只限制实例属性,不限制类属性、实例方法或类方法。类本身仍可以正常定义方法和类变量。
注意:实例方法是绑定在类上的,不是实例的属性,因此不受 slots 限制。
5. 继承中使用 slots 有哪些注意事项?
子类是否能添加新属性取决于父类是否定义了 __slots__:
- 父类未定义 slots:子类可以自由使用 __dict__,除非子类自己定义 slots
- 父类定义了 slots 且未包含 '__dict__':子类若想添加新属性,必须在自己的 slots 中声明,否则无法添加
- 多重继承中若多个父类定义了 slots,可能引发冲突,Python 不支持合并不同 slots 的机制
特别提醒:不要在多继承中让两个父类都有非空 slots,否则会报错。
6. 如何查看某个实例的 slots 属性?
可以通过访问类的 __slots__ 获取声明的字段名列表:
print(Point.__slots__) # 输出: ['x', 'y']
实例本身不能直接访问 __slots__,但可通过 type(instance).__slots__ 查看。
基本上就这些。理解清楚 slots 的作用范围和限制,就能避免大多数使用中的困惑。










