Python mixin


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 类通常遵循以下格式:

  1. 独立性:

    • Mixin 类应该是独立的,不依赖于任何特定的基类。它们应该提供可以与任何类组合使用的功能。
  2. 单一职责:

    • Mixin 类应该只负责提供一种特定的功能或特性,而不应该尝试实现太多的功能。这样可以让 Mixin 更加灵活和可重用。
  3. 命名约定:

    • Mixin 类的命名通常以 Mixin 作为后缀,例如 LoggingMixinCachingMixin 等,以明确它们的目的。
  4. 方法和属性命名:

    • Mixin 类中的方法和属性应该尽量避免与基类中的名称冲突。如果不可避免,可以考虑使用更加具体的名称。
  5. 无构造函数:

    • Mixin 类通常不需要自己的构造函数 __init__(),因为它们是用来添加功能,而不是创建完整的对象。
  6. 多个 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 方法,可以被 DogCat 类继承和使用。通过多重继承,DogCat 类同时继承了 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_jsonfrom_json 方法,用于将对象序列化为 JSON 格式,以及从 JSON 数据中创

参考: https://www.cnblogs.com/wongbingming/p/13785203.html

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值