Python中__slots__与继承共存需所有父类显式定义__slots__(含空元组),子类__slots__完全替代父类而非合并,多重继承时各基类均须遵守,否则报TypeError。

在 Python 中让 __slots__ 和继承共存是可行的,但需注意子类和父类的定义顺序与内容,否则会触发 TypeError: non-empty __slots__ must be same for all bases 等错误。核心原则是:**子类若定义了非空 __slots__,所有参与多重继承的父类也必须显式定义 __slots__(哪怕为空 tuple),且不能有冲突的属性名**。
父类必须显式声明 __slots__
如果父类没写 __slots__,Python 默认允许动态添加任意属性(即隐含 __dict__)。此时子类一旦定义非空 __slots__,就会因“混合了 __dict__ 和受限属性”而报错。
✅ 正确做法:所有父类都显式声明 __slots__,哪怕为空:
class Animal:
__slots__ = () # 允许继承,但不添加新属性
class Dog(Animal):
slots = ('name', 'breed')
子类 __slots__ 自动继承父类限制
子类的 __slots__ 不会自动合并父类的字段,而是**完全替代**(除非手动合并)。若想扩展属性,需显式包含父类的字段或用加法拼接:
立即学习“Python免费学习笔记(深入)”;
- 直接列出全部字段(推荐,清晰可控):
__slots__ = ('name', 'breed', 'age') - 用元组相加合并:
__slots__ = Animal.__slots__ + ('name', 'breed') - 避免重复定义同名字段,否则运行时不会报错但逻辑混乱
多重继承时所有基类都要有 __slots__
如果有多个父类(如 class RobotDog(Dog, Electronic)),则 Dog 和 Electronic 都必须定义 __slots__,哪怕其中一个只写 __slots__ = ()。
❌ 错误示例:
class Electronic: # 没有 __slots__
pass
class RobotDog(Dog, Electronic): # TypeError!
slots = ('battery_level',)
✅ 修复方式:
class Electronic:
__slots__ = () # 补上空 slots
class RobotDog(Dog, Electronic):
slots = ('battery_level',)
需要 __dict__ 或动态属性?谨慎放开
如果某类必须支持任意属性(比如做配置基类),可显式加入 '__dict__' 到 __slots__ 中,但这会让该类失去内存优化效果,且其子类若再定义 __slots__ 就不能再加 '__dict__'(否则冲突):
-
__slots__ = ('x', '__dict__')→ 允许x和其他任意属性 - 子类若写
__slots__ = ('y',),则y可用,但新增属性仍走__dict__;若子类也想用__dict__,无需重复写,它已从父类继承 - 不建议在继承链中间层加
'__dict__',容易破坏设计意图










