使用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中DJANGO简单测试实例
May 11 Python
windows下安装Python和pip终极图文教程
Mar 05 Python
详解PyCharm配置Anaconda的艰难心路历程
Aug 13 Python
十个Python练手的实战项目,学会这些Python就基本没问题了(推荐)
Apr 26 Python
python如何解析配置文件并应用到项目中
Jun 27 Python
python 修改本地网络配置的方法
Aug 14 Python
详解python 中in 的 用法
Dec 12 Python
python实现单目标、多目标、多尺度、自定义特征的KCF跟踪算法(实例代码)
Jan 08 Python
浅谈PyTorch的可重复性问题(如何使实验结果可复现)
Feb 20 Python
Pycharm最常用的快捷键及使用技巧
Mar 05 Python
Python GUI编程学习笔记之tkinter界面布局显示详解
Mar 30 Python
jupyter notebook 多环境conda kernel配置方式
Apr 10 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文件操作的详细诠释
2013/06/21 PHP
php调用c接口无错版介绍
2014/03/11 PHP
发一个自己用JS写的实用看图工具实现代码
2008/07/26 Javascript
js获取指定日期前后的日期代码
2013/08/20 Javascript
常用的几段javascript代码分享
2014/03/25 Javascript
jQuery实现返回顶部功能适合不支持js的浏览器
2014/08/19 Javascript
JS 拦截全局ajax请求实例解析
2016/11/29 Javascript
jQuery展示表格点击变色、全选、删除
2017/01/05 Javascript
Vue数据双向绑定的深入探究
2018/11/27 Javascript
微信小程序实现文字从右向左无限滚动
2020/11/18 Javascript
如何从0开始用node写一个自己的命令行程序
2018/12/29 Javascript
vue.js循环radio的实例
2019/11/07 Javascript
Vue页面切换和a链接的本质区别详解
2019/11/12 Javascript
关于AngularJS中几种Providers的区别总结
2020/05/17 Javascript
JavaScript async/await原理及实例解析
2020/12/02 Javascript
js实现电灯开关效果
2021/01/19 Javascript
javascript代码实现简易计算器
2021/01/25 Javascript
[54:10]Spirit vs NB Supermajor小组赛 A组败者组决赛 BO3 第一场 6.2
2018/06/03 DOTA
[04:54]DOTA2-DPC中国联赛1月31日Recap集锦
2021/03/11 DOTA
numpy.std() 计算矩阵标准差的方法
2018/07/11 Python
python实现文件助手中查看微信撤回消息
2019/04/29 Python
python global关键字的用法详解
2019/09/05 Python
Python原始套接字编程实例解析
2020/01/29 Python
Python 使用双重循环打印图形菱形操作
2020/08/09 Python
Python grequests模块使用场景及代码实例
2020/08/10 Python
如何创建一个Flask项目并进行简单配置
2020/11/18 Python
让IE9以下版本的浏览器兼容HTML5的方法
2014/03/12 HTML / CSS
Tessabit日本:集世界奢侈品和设计师品牌的意大利精品买手店
2020/01/07 全球购物
就业自荐信
2013/12/04 职场文书
高中校园广播稿
2014/01/11 职场文书
暑假家长评语大全
2014/04/17 职场文书
2015年领导班子工作总结
2015/05/23 职场文书
新员工入职感言范文!
2019/07/04 职场文书
工作违纪的检讨书范文
2019/07/09 职场文书
只用40行Python代码就能写出pdf转word小工具
2021/05/31 Python
关于SpringBoot 使用 Redis 分布式锁解决并发问题
2021/11/17 Redis