使用Mixin设计模式进行Python编程的方法讲解


Posted in Python onJune 21, 2016

Mixin模式是一种在python里经常使用的模式,适当合理的应用能够达到复用代码,合理组织代码结构的目的。

Python的Mixin模式可以通过多继承的方式来实现, 举例来说,我们自定义一个简单的具有嵌套结构的数据容器:

class SimpleItemContainer(object):
  def __init__(self, id, item_containers):
    self.id = id
    self.data = {}
    for item in item_containers:
      self.data[item.id] = item

SimpleItemContainer通过python内置类型Dict来存放数据,不过到目前为止想要访问对应的数据还是得直接调用里面的字典,没法像原生的字典一样方便的通过暴露出来的api访问数据。当然也可以从头开始把完整的Dictionary Interface完全实现个遍,不过在每个自定义的类似的容器中都来一套肯定不行,这时候利用python内置的UserDict.DictMixin就是一个不错的方式:

from UserDict import DictMixin

class BetterSimpleItemContainer(object, DictMixin):
  def __getitem__(self, id):
    return self.data[id]

  def __setitem__(self, id, value):
   self.data[id] = value

  def __delitem__(self, id):
   del self.data[id]

  def keys(self):
      return self.data.keys()

通过实现最小的Dictionary Interface,还有继承DictMixin实现Mixin模式,我们就轻松获得了完整的原生字典的行为:下表语法,get, has_keys, iteritems, itervalues甚至还有iterable protocol implementation等一系列的方法和实现。

很多框架比如Django, Django rest framework里面就普遍用到了Mixin这种模式,定义api或者viewset的时候就能够通过多重继承的方式服用一些功能

当然,Mixin模式也不能滥用,至少他会污染你新定义的类,有时候还会带来MRO的问题;不过把一些基础和单一的功能比如一般希望通过interface/protocol实现的功能放进Mixin模块里面还是不错的选择:

class CommonEqualityMixin(object):

  def __eq__(self, other):
    return (isinstance(other, self.__class__)
      and self.__dict__ == other.__dict__)

  def __ne__(self, other):
    return not self.__eq__(other)

class Foo(CommonEqualityMixin):

  def __init__(self, item):
    self.item = item

其实整个理解下来无非就是通过组合的方式获得更多的功能,有点像C#, java里面的interface,强调“it can”的意思,但相比起来简单多了,不需要显示的约束,而且mixin模块自带实现。在使用的时候一般把mixin的类放在父类的右边似乎也是为了强调这并不是典型的多继承,是一种特殊的多继承,而是在继承了一个基类的基础上,顺带利用多重继承的功能给这个子类添点料,增加一些其他的功能。保证Mixin的类功能单一具体,混入之后,新的类的MRO树其实也会相对很简单,并不会引起混乱。

Python 相关文章推荐
Python装饰器的函数式编程详解
Feb 27 Python
python解决pandas处理缺失值为空字符串的问题
Apr 08 Python
在IPython中进行Python程序执行时间的测量方法
Nov 01 Python
python使用Plotly绘图工具绘制水平条形图
Mar 25 Python
使用python搭建服务器并实现Android端与之通信的方法
Jun 28 Python
python numpy 常用随机数的产生方法的实现
Aug 21 Python
python调用函数、类和文件操作简单实例总结
Nov 29 Python
python 输出列表元素实例(以空格/逗号为分隔符)
Dec 25 Python
Python实现投影法分割图像示例(一)
Jan 17 Python
利用setuptools打包python程序的方法步骤
Jan 18 Python
如何将tensorflow训练好的模型移植到Android (MNIST手写数字识别)
Apr 22 Python
pytorch加载自己的图像数据集实例
Jul 07 Python
详解Python中的from..import绝对导入语句
Jun 21 #Python
Java多线程编程中ThreadLocal类的用法及深入
Jun 21 #Python
深入解析Python中的__builtins__内建对象
Jun 21 #Python
浅谈Python中函数的参数传递
Jun 21 #Python
对比Python中__getattr__和 __getattribute__获取属性的用法
Jun 21 #Python
常见python正则用法的简单实例
Jun 21 #Python
小议Python中自定义函数的可变参数的使用及注意点
Jun 21 #Python
You might like
PHP分页显示制作详细讲解
2006/10/09 PHP
我的论坛源代码(十)
2006/10/09 PHP
php 无限分类的树类代码
2009/12/03 PHP
php设计模式 Singleton(单例模式)
2011/06/26 PHP
php递归创建目录的方法
2015/02/02 PHP
phpstudy2020搭建站点的实现示例
2020/10/30 PHP
基于jQuery的输入框无值自动显示指定数据的实现代码
2011/01/24 Javascript
JavaScript 产生不重复的随机数三种实现思路
2012/12/13 Javascript
jQuery 淡出一个图像到另一个图像的实现代码
2013/06/12 Javascript
jQuery源码分析之jQuery中的循环技巧详解
2014/09/06 Javascript
JavaScript开发人员的10个关键习惯小结
2014/12/05 Javascript
第一次接触神奇的Bootstrap导航条
2016/08/09 Javascript
jQuery实现可拖拽3D万花筒旋转特效
2017/01/03 Javascript
jquery easyui DataGrid简单示例
2017/01/23 Javascript
原生js实现可拖拽效果
2017/02/28 Javascript
JavaScript中的普通函数和箭头函数的区别和用法详解
2017/03/21 Javascript
JS获取填报扩展单元格控件的值的解决办法
2017/07/14 Javascript
微信小程序数据分析之自定义分析的实现
2018/08/17 Javascript
浅谈Javascript常用正则表达式应用
2019/03/08 Javascript
VUE 实现复制内容到剪贴板的两种方法
2019/04/24 Javascript
vue路由守卫及路由守卫无限循环问题详析
2019/09/05 Javascript
[03:32]2014DOTA2西雅图邀请赛 CIS外卡赛赛前black专访
2014/07/09 DOTA
Python 字符串操作实现代码(截取/替换/查找/分割)
2013/06/08 Python
python创建进程fork用法
2015/06/04 Python
浅谈django model postgres的json字段编码问题
2018/01/05 Python
使用python进行拆分大文件的方法
2018/12/10 Python
python爬虫爬取微博评论案例详解
2019/03/27 Python
基于python的socket实现单机五子棋到双人对战
2020/03/24 Python
Shopty西班牙:缝纫机在线销售
2018/01/26 全球购物
应征英语教师求职信
2013/11/27 职场文书
电子技术专业中专生的自我评价
2013/12/17 职场文书
《落花生》教学反思
2014/02/25 职场文书
兵马俑的导游词
2015/02/02 职场文书
感恩母亲节活动总结
2015/02/10 职场文书
个人工作总结(管理人员)范文
2019/08/13 职场文书
创业计划书之情侣餐厅
2019/09/29 职场文书