Python 中的 Mixin 类是一种特殊的继承机制,它允许我们在不修改类层次结构的情况下,向一个类添加额外的功能。Mixin 类通常包含一些可复用的方法或属性,可以被其他类继承和使用。
认识Mixin模式
那我们今天就来讲讲这个 Mixin,对于这个Mixin,如何理解?它其实是一种设计模式,如果开发者之间没有产生这样一种设计模式的共识,那么设计模式将不复存在。
为了让大家,对这个 Mixin 有一个更直观的理解,我摘录了网上一段说明。
继承是一个”is-a”关系
。比如轿车类继承交通工具类,因为轿车是一个(“is-a”)交通工具。一个物品不可能是多种不同的东西,因此就不应该存在多重继承。不过有没有这种情况,一个类的确是需要继承多个类呢?
答案是有,我们还是拿交通工具来举例子,民航飞机是一种交通工具,对于土豪们来说直升机也是一种交通工具。对于这两种交通工具,它们都有一个功能是飞行,但是轿车没有。所以,我们不可能将飞行功能写在交通工具这个父类中。但是如果民航飞机和直升机都各自写自己的飞行方法,又违背了代码尽可能重用的原则(如果以后飞行工具越来越多,那会出现许多重复代码)。
怎么办,那就只好让这两种飞机同时继承交通工具以及飞行器两个父类,这样就出现了多重继承。这时又违背了继承必须是”is-a”关系。这个难题该怎么破?
这时候 Mixin 就闪亮登场了。飞行只是飞机做为交通工具的一种(增强)属性,我们可以为这个飞行的功能单独定义一个(增强)类,称之为 Mixin 类。这个类,是做为增强功能,添加到子类中的。为了让其他开发者,一看就知道这是个 Mixin 类,一般都要求开发者遵循规范,在类名末尾加上 Mixin
。
举个例子
class Vehicle(object):
pass
class PlaneMixin(object):
def fly(self):
print('I am flying')
class Airplane(Vehicle, PlaneMixin):
pass
使用Mixin类实现多重继承要遵循以下几个规范
- 责任明确:必须表示某一种功能,而不是某个物品;
- 功能单一:若有多个功能,那就写多个Mixin类;
- 绝对独立:不能依赖于子类的实现;子类即便没有继承这个Mixin类,也照样可以工作,就是缺少了某个功能
不使用Mixin的弊端
你肯定会问,不使用 Mixin 行吗?
当然可以,这个问题就像在问,我不遵循 PEP8 代码规范行吗?完全没问题,只是不推荐那样做。
那么到底有什么理由,让我们要去用到 Mixin 设计模式呢?
不使用的话,大概有如下三点弊端:
- 1、结构复杂
单继承中一个类的父类是什么,父类的父类是什么非常明确。多继承一个类有多个父类,父类又有多个父类,继承关系复杂。
- 2、优先顺序模糊
多个父类中有同名方法,在开发过程中,容易造成思维混乱,子类不知道继承哪个父类,会增加开发难度。关于子类的继承顺序,有一个比较复杂的 C3 算法,如果你还不清楚,可以点击我的另一篇文章 ,了解一下。
- 3、功能冲突
多重继承有多个父类,但是子类只能继承一个,对于同名方法,就会导致另一个父类的方法失效。
在 Python 中,Mixin 类通常遵循以下格式:
在 Python 中,Mixin 类通常遵循以下格式:
-
独立性:
- Mixin 类应该是独立的,不依赖于任何特定的基类。它们应该提供可以与任何类组合使用的功能。
-
单一职责:
- Mixin 类应该只负责提供一种特定的功能或特性,而不应该尝试实现太多的功能。这样可以让 Mixin 更加灵活和可重用。
-
命名约定:
- Mixin 类的命名通常以
Mixin
作为后缀,例如LoggingMixin
、CachingMixin
等,以明确它们的目的。
- Mixin 类的命名通常以
-
方法和属性命名:
- Mixin 类中的方法和属性应该尽量避免与基类中的名称冲突。如果不可避免,可以考虑使用更加具体的名称。
-
无构造函数:
- Mixin 类通常不需要自己的构造函数
__init__()
,因为它们是用来添加功能,而不是创建完整的对象。
- Mixin 类通常不需要自己的构造函数
-
多个 Mixin 的组合:
- 一个类可以同时继承多个 Mixin 类,从而获得多种功能。这种组合方式非常灵活。
下面是一个简单的 Mixin 类示例:
class LogMixin:
def log(self, message):
print(f"[LOG] {message}")
class Animal:
def __init__(self, name):
self.name = name
def speak(self):
raise NotImplementedError("Subclasses must implement the speak method")
class Dog(Animal, LogMixin):
def speak(self):
self.log(f"{self.name} says: Woof!")
class Cat(Animal, LogMixin):
def speak(self):
self.log(f"{self.name} says: Meow!")
# 使用 Mixin 类
dog = Dog("Buddy")
dog.speak() # Output: [LOG] Buddy says: Woof!
cat = Cat("Whiskers")
cat.speak() # Output: [LOG] Whiskers says: Meow!
在这个例子中, LogMixin
类包含一个 log
方法,可以被 Dog
和 Cat
类继承和使用。通过多重继承,Dog
和 Cat
类同时继承了 Animal
类和 LogMixin
类,从而获得了 speak
方法和 log
方法。
Mixin 类的另一个常见用法是为现有类添加功能。例如,你可以创建一个 SerializableMixin
类,为其他类添加序列化和反序列化的功能:
import json
class SerializableMixin:
def to_json(self):
return json.dumps(self.__dict__)
@classmethod
def from_json(cls, json_data):
obj = cls()
obj.__dict__.update(json.loads(json_data))
return obj
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
class Employee(Person, SerializableMixin):
def __init__(self, name, age, job_title):
super().__init__(name, age)
self.job_title = job_title
# 使用 Mixin 类
employee = Employee("John Doe", 35, "Software Engineer")
json_data = employee.to_json()
print(json_data) # Output: {"name": "John Doe", "age": 35, "job_title": "Software Engineer"}
new_employee = Employee.from_json(json_data)
print(new_employee.name, new_employee.age, new_employee.job_title) # Output: John Doe 35 Software Engineer
在这个例子中, SerializableMixin
类提供了 to_json
和 from_json
方法,用于将对象序列化为 JSON 格式,以及从 JSON 数据中创
参考: https://www.cnblogs.com/wongbingming/p/13785203.html