mixin通过多重继承实现功能复用,需轻量无状态、不定义__init__、用__slots__=()声明,置于主类前以确保mro正确,命名带mixin后缀且职责单一。

在 Class 中实现 Mixin,核心是用多重继承把专注功能的类“插”进来,而不是靠层层继承构建类型关系。它不追求“是什么”,而解决“能做什么”。
Mixin 类要轻量、无状态
Mixin 类通常不定义 __init__,也不维护实例变量(比如不用 self._xxx 存状态)。它的职责就是提供方法,且这些方法依赖 super() 向下委托,假设被混入的类已具备基础行为(如 __setitem__、__getitem__)。
- 用 __slots__ = () 明确表示无实例属性
- 避免在 Mixin 中初始化资源或连接(如数据库、文件句柄)
- 如果必须初始化,需确保调用 super().__init__() 并兼容其他父类
继承顺序决定行为链路
Python 的方法解析顺序(MRO)从左到右扫描继承列表。Mixin 必须放在主类(如 dict、BaseRequest)之前,才能让它的方法优先被查到,并通过 super() 正确跳转到后续类。
- ✅ 正确:class Article(TimestampMixin, BaseModel): pass
- ❌ 错误:class Article(BaseModel, TimestampMixin): pass(Mixin 方法可能被跳过)
- 可通过 Article.__mro__ 查看实际调用链,验证顺序是否符合预期
命名与职责要清晰单一
一个 Mixin 只做一件事,名字应直接体现能力,比如 JSONSerializableMixin、SetOnceMappingMixin。多个 Mixin 可叠加,但彼此不能有逻辑耦合或隐式依赖。
- 命名推荐带 Mixin 后缀,便于团队识别用途
- 避免在 Mixin 中调用另一个 Mixin 的方法(除非明确设计为组合)
- 测试时可单独对 Mixin 行为验证,例如传入一个模拟的 dict 子类来检查 __setitem__ 是否拦截成功
典型使用场景示例
比如给字典增加日志和单次赋值限制:
- class LoggedDict(LoggedMappingMixin, SetOnceMappingMixin, dict): pass
- 创建实例后,d['x'] = 1 触发日志并检查是否重复;再赋值会报错
- 所有功能来自 Mixin,dict 本身未被修改,复用性高











