Mixin 的概念

Mixin 即 Mix-in,常被译为“混入”,是一种编程模式,在 Python 等面向对象语言中,通常它是实现了某种功能单元的类,用于被其他子类继承,将功能组合到子类中。

利用 Python 的多重继承,子类可以继承不同功能的 Mixin 类,按需动态组合使用。

当多个类都实现了同一种功能时,这时应该考虑将该功能抽离成 Mixin 类。

举个例子

定义一个简单的类:

class Person:
def __init__(self, name, gender, age):
self.name = name
self.gender = gender
self.age = age

我们可以通过调用实例属性的方式来访问:

p = Person("小陈", "男", 18)
print(p.name) # "小陈"

然后我们定义一个 Mixin 类:

class MappingMixin:
def __getitem__(self, key):
return self.__dict__.get(key) def __setitem__(self, key, value):
return self.__dict__.set(key, value)

这个类可以让子类拥有像 dict 一样调用属性的功能

我们将这个 Mixin 加入到 Person 类中:

class Person(MappingMixin):
def __init__(self, name, gender, age):
self.name = name
self.gender = gender
self.age = age

现在 Person 拥有另一种调用属性方式了:

p = Person("小陈", "男", 18)
print(p['name']) # "小陈"
print(p['age']) # 18

再定义一个 Mixin 类,这个类实现了 __repr__ 方法,能自动将属性与值拼接成字符串:

class ReprMixin:
def __repr__(self):
s = self.__class__.__name__ + '('
for k, v in self.__dict__.items():
if not k.startswith('_'):
s += '{}={}, '.format(k, v)
s = s.rstrip(', ') + ')' # 将最后一个逗号和空格换成括号
return s

利用 Python 的特性,一个类可以继承多个父类:

class Person(MappingMixin, ReprMixin):
def __init__(self, name, gender, age):
self.name = name
self.gender = gender
self.age = age

这样这个子类混入了两种功能:

p = Person("小陈", "男", 18)
print(p['name']) # "小陈"
print(p) # Person(name=小陈, gender=男, age=18)

总结

Mixin 实质上是利用语言特性,可以把它看作一种特殊的多重继承,所以它并不是 Python 独享,只要支持多重继承或者类似特性的都可以使用,比如 Ruby 中 include 语法,Vue 等前端领域也有 Mixin 的概念。

但 Mixin 终归不属于语言的语法,为了代码的可读性和可维护性,定义和使用 Mixin 类应该遵循几个原则:

  1. Mixin 实现的功能需要是通用的,并且是单一的,比如上例中两个 Mixin 类都适用于大部分子类,每个 Mixin 只实现一种功能,可按需继承。
  2. Mixin 只用于拓展子类的功能,不能影响子类的主要功能,子类也不能依赖 Mixin。比如上例中 Person 继承不同的 Mixin 只是增加了一些功能,并不影响自身的主要功能。如果是依赖关系,则是真正的基类,不应该用 Mixin 命名。
  3. Mixin 类自身不能进行实例化,仅用于被子类继承。

本文属于原创,首发于微信公众号「面向人生编程」,如需转载请后台留言。

关注后回复以下信息获取更多资源

回复【资料】获取 Python / Java 等学习资源

回复【插件】获取爬虫常用的 Chrome 插件

回复【知乎】获取最新知乎模拟登录

最新文章

  1. 关于Linq中的Lambda表达式中OrderBy的深入理解
  2. 最全面的 C++ 资源、框架大全
  3. SQL触发器实例讲解
  4. 从其它系统登录到SharePoint 2010系统的单点登录
  5. sql server压缩数据库和日志文件
  6. 【JS】js获得下拉列表选中项的值和id
  7. php代码锁
  8. (转载)提高mysql插入数据的速度
  9. 贪心 uvaoj 11134 Fabled Rooks
  10. jquery.cookie.js 的配置
  11. pom文件
  12. git stash命令详解
  13. (String)强制转换、toString()和String.valueOf()的区别
  14. Python包管理工具pip安装
  15. maven 打包可执行jar的方法
  16. cordova 加载HTML 资源的次序
  17. 页面元素定位 XPath 简介
  18. 第十一章 springboot + mongodb(简单查询)
  19. vlc的应用之七:用vlc做单播,组播及点播服务器【转】
  20. python程序设计——面向对象程序设计:属性

热门文章

  1. Bran的内核开发教程(bkerndev)-07 中断描述符表(IDT)
  2. mysql全局变量和局部变量
  3. Tesseract引擎编译
  4. 路由传参 query 和 params
  5. tarjan学习(复习)笔记(持续更新)(各类找环模板)
  6. 8.3 NOIP 模拟12题解
  7. L1与L2正则化的对比及多角度阐述为什么正则化可以解决过拟合问题
  8. VM 使用问题 | 安装失败->>注册表
  9. pycharm的部分个性化设置及快捷键
  10. Mysql备份还有这么多套路,还不了解下?