当前位置: 首页 > news >正文

Python 中的 Mixin

Mixin 是 OOP 中的一种工具,一个用于传递一种特定行为的容器,多个类可以共享该行为,而无需建立“ is-a”(父子)关系,同时保持它们之间的松耦合

Python 依赖多重继承作为底层机制来实现 Mixin

Python 的 mixin 是具有特殊含义的普通类,和普通类之间没有语法差异——区别纯粹是语义上的

继承的缺点

过度泛化:当基类的范围变得过于宽泛时,子类就会开始继承不必要的特性

Erlang的创建者乔·阿姆斯特朗在接受Coders at Work的采访时,巧妙地描述了这个问题:

因为面向对象语言的问题在于,它们自带了各种隐式环境。你想要一根香蕉,结果得到的却是一只叼着香蕉的大猩猩和整片丛林

—乔·阿姆斯特朗

更好的方法是根据类的作用而不是其本身来设计类

这意味着优先考虑组合而不是继承,并将职责委托给更小、更专注的组件

mixin 是一把双刃剑

特点

class SerializableMixin:def serialize(self) -> dict:if hasattr(self, "__slots__"):return {name: getattr(self, name)for name in self.__slots__}else:return vars(self)
  • 命名规范:并非强制要求,类名以Mixin结尾
  • 普通类:由于 mixin 旨在提供独立、可复用的功能(而非强制继承结构),因此它们通常没有任何父类。这最大限度地减少了它们的作用域,并降低了在多重继承场景中名称解析错误的可能性

万事无绝对,有时也可能相反,将各个 Mixin 共同的部分收集到一个父类中可能有助于维护,如 Django 提供的 PermissionRequiredMixinLoginRequiredMixin,都继承AccessMixin

  • 单一职责:一个 mixin 类只有一个职责
  • 无状态性: Mixin 很少定义自己的构造函数__init__()或实例属性,这使得它们可以通过多重继承安全地与其他类集成,而不会发生冲突。Mixin 类封装的行为仅依赖于外部状态。Mixin 通常依赖于其混合到的类的属性。
  • 非独立实体: Mixin 旨在为其他类添加新的或修改的行为。它们通常独立存在时没有任何意义,因此几乎不会直接实例化 mixin 类

Mixin 单独使用没有作用:

import json
class JSONSerializableMixin:def as_json(self) -> str:return json.dumps(vars(self))>>> mixin_instance = JSONSerializableMixin()
>>> mixin_instance.as_json()
'{}'

只有继承之后会发挥作用:

from dataclasses import dataclass@dataclass
class User(JSONSerializableMixin):user_id: intemail: str>>> User(555, "jdoe@example.com").as_json()
'{"user_id": 555, "email": "jdoe@example.com"}'

继承🆚Mixin

继承通常可以从两个方面理解:

  1. 实现代码复用
  2. 作为建立子类型关系的工具

这两种用法也分别称为实现继承接口继承

mixin 主要侧重于代码复用,而非强“is a”关系

继承自 mixin 的类不会成为其子类型,只是使用其功能。

由于 mixin 并非旨在实现多态性,因此将其视为可与其基类互换通常违反了里氏代换原则

抽象类🆚Mixin

相同点:二者都是基础元素,旨在通过继承与一个或多个目标类组合

不同点:抽象类旨在被子类化以多态方式使用。它们通常具有父类

此外,声明 ABC 需要使用特殊的元类装饰器,Python 可以利用它们运行额外的检查:

from abc import ABC, abstractmethod
from typing import Anyclass Serializer(ABC):@abstractmethoddef serialize(self, data: Any) -> str:pass>>> abc_instance = Serializer()
TypeError: Can't instantiate abstract class Serializer
⮑ without an implementation for abstract method 'serialize'

使用抽象基类来定义算法的核心实现,同时在子类之间强制使用通用接口。这使得抽象基类 (ABC) 特别适合实现模板方法模式

Mixin 继承顺序

利用 Django 提供的 Mixin 与 ListView 实现一个图书列表页面:

class BookListView(LoginRequiredMixin, PermissionRequiredMixin, ListView):

不必严格依赖 MRO 就能利用好 mixin 。mixin 在与其他基类一起使用时才能发挥最大作用,但这有时会导致一些意想不到的行为

常见问题

  1. 过度使用:一个类继承的 Mixin 不要过多,功能繁杂可能导致其成为上帝对象
  2. 继承顺序错误:由于 Python 采用 C3 超类线性化算法决定 MRO( 靠左优先的类继承),需处理好 mixin 的继承顺序,否则不同 mixin 功能可能有冲突、重叠,甚至相互抵消

未完待续

http://www.lryc.cn/news/615678.html

相关文章:

  • 第4章 程序段的反复执行2 while语句P128练习题(题及答案)
  • 【动态数据源】⭐️@DS注解实现项目中多数据源的配置
  • Datawhale AI夏令营第三期,多模态RAG方向 Task2
  • 深度学习入门Day8:生成模型革命——从GAN到扩散模型
  • pytorch llm 计算flops和参数量
  • Busybox编译、制作initramfs,并在QEMU中运行
  • 束搜索(Beam Search):原理、演进与挑战
  • Java -- 日期类-第一代-第二代-第三代日期
  • NLP:Transformer输出部分
  • 第十九天-输入捕获实验
  • AI编程工具 | Trae介绍
  • Linux高级编程-文件操作
  • SpringBoot 集成 MapStruct
  • Vue 3.6 Vapor模式完全指南:告别虚拟DOM,性能飞跃式提升
  • 使用GTX ip core + SDI IP core实现SDI设计
  • Vue3 路由
  • C++算法练习:单词识别
  • 决策树技术详解:从理论到Python实战
  • 【ref、toRef、toRefs、reactive】
  • 多级缓存详解
  • 《励曼旋耕》Liman Rotary Tillage
  • Python如何合并两个Excel文件
  • 花生4CL基因家族鉴定及对干旱与盐胁迫响应分析--文献精读157
  • 本地进行语音文字互转
  • CVPR中深度学习新范式:通用性、鲁棒性与多模态的创新突破
  • 分布式事务Seata TCC模式篇
  • Linux网络转发系统框架分析
  • 【密码学】7. 数字签名
  • orcad的操作(1)
  • 【LLM】Openai之gpt-oss模型和GPT5模型