Python 混入类 Mix-in 和多继承

1,834 阅读2分钟

Simple is better than Complex. --- The Zen of Python.

混入类是什么?

简单的理解,我们做个句子扩展的游戏:

  1. 混入类是一个类。

  2. 混入类是一个 可以对其他类添加额外功能 的类。

  3. 混入类是一个可以 通过多继承 对其他类添加额外功能 的类。

像是 Python 的装饰器,又像是插件。

快速开始

来看一个例子,我们有:

  • 基类 载具 Vehicle

  • 混入类 对讲机 SpeakerMixin

  • 混入类 加农炮 Canon

  • 载具的子类 飞机Plane

  • 载具的子类 坦克Panzer`

来看代码:

class Vehicle:
    """ 载具基类。 """
    def __init__(self, name):
        self.name = name


class SpeakerMixin(object):
    """ 混入类:对讲机。"""
    def speak(self, msg='hello'):
        print(f'[{self.name}]: {msg}')


class CannonMixin(object):
    """ 混入类:加农炮。"""
    def fire(self):
        print(f'[{self.name} Fired]')


class Plane(Vehicle, SpeakerMixin):
    """ 子类:飞机。"""
    ...


class Panzer(Vehicle, SpeakerMixin, CannonMixin):
    """ 子类:坦克。"""
    ...


if __name__ == "__main__":
    # 实例化飞机和坦克
    plane = Plane("Boein 747")
    panzer = Panzer('Panzer 99')
    
    # 利用对讲机对话
    plane.speak('Panzer 99, move!')
    panzer.speak('Roger that!')
    panzer.speak('On the position now.')
    plane.speak('Fire!')
    
    # 坦克加农炮开火
    panzer.fire()

运行输出:

[Boein 747]: Panzer 99, move!
[Panzer 99]: Roger that!
[Panzer 99]: On the position now.
[Boein 747]: Fire!
[Panzer 99 Fired]

混入类就像是一个插件,可拔插又不破坏被混入的类。拿上面的例子来说,我们要改造一下我们的坦克,加入一个雷达功能:

class RadarMixin(object):
    def detect(self):
        print(f'[{self.name}]: Radar detecting...')

接下来把混入类 RadarMixin 加入到坦克类中:


class Panzer(Vehicle, SpeakerMixin, CannonMixin, RadarMixin):
    """ 子类:坦克。"""
    ...

在 main 部分代码加入调用:

if __name__ == "__main__":
    # 实例化飞机和坦克
    plane = Plane("Boein 747")
    panzer = Panzer('Panzer 99')
    
    # 利用对讲机对话
    plane.speak('Panzer 99, move!')
    panzer.speak('Roger that!')
    panzer.speak('On the position now.')
    plane.speak('Fire!')
    
    # 雷达开始扫描
    panzer.detect()
    # 坦克加农炮开火
    panzer.fire()

输出结果:

[Boein 747]: Panzer 99, move!
[Panzer 99]: Roger that!
[Panzer 99]: On the position now.
[Boein 747]: Fire!
[Panzer 99]: Radar detecting...
[Panzer 99 Fired]