使用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中的包和模块实例
Nov 22 Python
Python用GET方法上传文件
Mar 10 Python
Python数据操作方法封装类实例
Jun 23 Python
详解appium+python 启动一个app步骤
Dec 20 Python
Python3实现带附件的定时发送邮件功能
Dec 22 Python
python selenium 获取标签的属性值、内容、状态方法
Jun 22 Python
python消除序列的重复值并保持顺序不变的实例
Nov 08 Python
python实现指定字符串补全空格、前面填充0的方法
Nov 16 Python
解决python执行不输出系统命令弹框的问题
Jun 24 Python
浅谈Python3 numpy.ptp()最大值与最小值的差
Aug 24 Python
Django框架安装方法图文详解
Nov 04 Python
运行Python编写的程序方法实例
Oct 21 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
服务器变量 $_SERVER 的深入解析
2013/07/02 PHP
php生成二维码
2015/08/10 PHP
PHP手机号中间四位用星号*代替显示的实例
2017/06/02 PHP
PHP文件管理之实现网盘及压缩包的功能操作
2017/09/20 PHP
thinkPHP5框架闭包函数与子查询传参用法示例
2018/08/02 PHP
PHP实现会员账号单唯一登录的方法分析
2019/03/07 PHP
thinkPHP5使用Rabc实现权限管理
2019/08/28 PHP
JavaScript 异步调用框架 (Part 3 - 代码实现)
2009/08/04 Javascript
javascript开发随笔二 动态加载js和文件
2011/11/25 Javascript
Jquery实现显示和隐藏的4种简单方式
2013/08/28 Javascript
JS.findElementById()使用介绍
2013/09/21 Javascript
BAT及各大互联网公司2014前端笔试面试题--JavaScript篇
2014/10/29 Javascript
JavaScript替换当前页面的方法
2015/04/03 Javascript
浅析JavaScript中的变量复制、参数传递和作用域链
2016/01/13 Javascript
JS表单验证的代码(常用)
2016/04/08 Javascript
jQuery实现验证码功能
2017/03/17 Javascript
想用好React的你必须要知道的一些事情
2017/07/24 Javascript
手把手教你如何编译打包video.js
2020/12/09 Javascript
全面解读Python Web开发框架Django
2014/06/30 Python
Python的time模块中的常用方法整理
2015/06/18 Python
Python 类的继承实例详解
2017/03/25 Python
python实现朴素贝叶斯分类器
2018/03/28 Python
Python当中的array数组对象实例详解
2019/06/12 Python
Python Numpy计算各类距离的方法
2019/07/05 Python
pytorch 加载(.pth)格式的模型实例
2019/08/20 Python
Python制作词云图代码实例
2019/09/09 Python
django ListView的使用 ListView中获取url中的参数值方式
2020/03/27 Python
服务器端jupyter notebook映射到本地浏览器的操作
2020/04/14 Python
简单了解python shutil模块原理及使用方法
2020/04/28 Python
Django如何实现密码错误报错提醒
2020/09/04 Python
Python实现定时监测网站运行状态的示例代码
2020/09/30 Python
英国助听器购物网站:Hearing Direct
2018/08/21 全球购物
大学社团活动总结
2014/04/26 职场文书
珍爱生命演讲稿
2014/05/10 职场文书
2014年教师节座谈会发言稿
2014/09/10 职场文书
开业庆典致辞
2015/08/01 职场文书