使用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实现百万答题自动百度搜索答案
Jan 16 Python
python skimage 连通性区域检测方法
Jun 21 Python
把JSON数据格式转换为Python的类对象方法详解(两种方法)
Jun 04 Python
python批量修改图片尺寸,并保存指定路径的实现方法
Jul 04 Python
Python数学形态学实例分析
Sep 06 Python
Python 内置函数globals()和locals()对比详解
Dec 23 Python
python异常处理和日志处理方式
Dec 24 Python
Django调用百度AI接口实现人脸注册登录代码实例
Apr 23 Python
Keras设定GPU使用内存大小方式(Tensorflow backend)
May 22 Python
Pytest单元测试框架如何实现参数化
Sep 05 Python
基于Django快速集成Echarts代码示例
Dec 01 Python
python 中 .py文件 转 .pyd文件的操作
Mar 04 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面向对象全攻略 (五) 封装性
2009/09/30 PHP
php获取是星期几的的一些常用姿势
2019/12/15 PHP
JS 遮照层实现代码
2010/03/31 Javascript
兼容IE与firefox火狐的回车事件(js与jquery)
2010/10/20 Javascript
jquery聚焦文本框与扩展文本框聚焦方法
2012/10/12 Javascript
一款jquery特效编写的大度宽屏焦点图切换特效的实例代码
2013/08/05 Javascript
SeaJS入门教程系列之使用SeaJS(二)
2014/03/03 Javascript
招聘网站基于jQuery实现自动刷新简历
2015/05/10 Javascript
chrome浏览器当表单自动填充时如何去除浏览器自动添加的默认样式
2015/10/09 Javascript
jQuery实现仿QQ空间装扮预览图片的鼠标提示效果代码
2015/10/30 Javascript
实用jquery操作表单元素的简单代码
2016/07/04 Javascript
在js中实现邮箱格式的验证方法(推荐)
2016/10/24 Javascript
详解网站中图片日常使用以及优化手法
2017/01/09 Javascript
最全正则表达式总结:验证QQ号、手机号、Email、中文、邮编、身份证、IP地址等
2017/08/16 Javascript
Node.js使用MySQL连接池的方法实例
2018/02/11 Javascript
JS闭包原理与应用经典示例
2018/12/20 Javascript
详解element-ui中el-select的默认选择项问题
2019/08/02 Javascript
layui table数据修改的回显方法
2019/09/04 Javascript
JS运算符简单用法示例
2020/01/19 Javascript
vue实现日历表格(element-ui)
2020/09/24 Javascript
React实现评论的添加和删除
2020/10/20 Javascript
Python中使用中文的方法
2011/02/19 Python
推荐10款最受Python开发者欢迎的Python IDE
2018/09/16 Python
python地震数据可视化详解
2019/06/18 Python
python模拟点击网页按钮实现方法
2020/02/25 Python
python数据类型强制转换实例详解
2020/06/22 Python
使用CSS3实现SVG路径描边动画效果入门教程
2019/10/21 HTML / CSS
Html5移动端div固定到底部实现底部导航条的几种方式
2021/03/09 HTML / CSS
土木工程专业自荐信
2013/10/04 职场文书
单身联谊活动方案
2014/01/29 职场文书
委托公证书范本
2014/04/03 职场文书
领导干部对照检查材料
2014/08/24 职场文书
爱护公物演讲稿
2014/09/09 职场文书
开展批评与自我批评发言材料
2014/10/17 职场文书
2014年部门工作总结
2014/11/12 职场文书
深入浅出讲解Java8函数式编程
2022/01/18 Java/Android