__slots__ 直接报 AttributeError 是因为禁用 __dict__ 后无字典可写,赋值时找不到存储位置;仅允许 __slots__ 明确声明的属性(如 'name' 'age'),例外包括显式加入 '__dict__' 或 '__weakref__'、类属性及方法,但子类未定义 __slots__ 会自动恢复 __dict__。

__slots__ 为什么直接报 AttributeError 而不是静默忽略
因为 Python 实例默认靠 __dict__ 字典存属性,赋值语句 obj.x = 1 实际是往这个字典里写键值对。一旦类定义了 __slots__,解释器就不再为实例分配 __dict__,改用固定内存块(类似 C struct)存放预声明字段——没有字典,obj.new_attr = 123 就找不到地方写,直接触发 AttributeError。
__slots__ = ('name', 'age') 后还能加哪些东西
只能加列表里明写的字段,比如 name 和 age;其他一律禁止。但注意几个例外:
-
__slots__不限制类属性(如MyClass.version = '1.0')或方法 - 如果显式把
'__dict__'加进元组,比如__slots__ = ('name', '__dict__'),就能恢复动态添加能力,但失去内存优势 -
__weakref__也得手动加入才能支持弱引用,否则weakref.ref(obj)会失败
子类没写 __slots__ 就彻底失效
父类用了 __slots__,子类如果不定义自己的 __slots__,它会自动获得完整的 __dict__,所有动态添加都畅通无阻——这不是 bug,是设计行为。想锁死整个继承链,必须每个类都显式声明:
class A:
__slots__ = ('x',)
class B(A):
__slots__ = ('y',) # B 实例只允许 x 和 y
class C(B):
__slots__ = ('z',) # C 实例只允许 x、y、z
调试时 vars(obj) 报错怎么办
vars() 内部依赖 obj.__dict__,__slots__ 下它必然失败。替代方案是:
- 用
getattr(obj, attr)配合obj.__slots__手动遍历 - 写个简单函数:
dict((k, getattr(obj, k)) for k in obj.__slots__) - 别用
vars(),改用 IDE 的变量查看器或dir(obj)粗略看有哪些可访问名
真正难防的不是语法错误,而是团队里有人在子类漏写 __slots__,上线后才因意外赋值暴露问题——这种事静态检查工具根本抓不到。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











