使用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实现基本进制转换的方法
Jul 11 Python
好用的Python编辑器WingIDE的使用经验总结
Aug 31 Python
Python中 Lambda表达式全面解析
Nov 28 Python
Python文件操作,open读写文件,追加文本内容实例
Dec 14 Python
python编程羊车门问题代码示例
Oct 25 Python
Python简单生成随机数的方法示例
Mar 31 Python
基于Python 装饰器装饰类中的方法实例
Apr 21 Python
Python 将Matrix、Dict保存到文件的方法
Oct 30 Python
浅谈pytorch卷积核大小的设置对全连接神经元的影响
Jan 10 Python
python如何实现复制目录到指定目录
Feb 13 Python
Python切割图片成九宫格的示例代码
Mar 10 Python
python 基于UDP协议套接字通信的实现
Jan 22 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中关键字interface和implements详解
2017/06/14 PHP
php libevent 功能与使用方法详解
2020/03/04 PHP
关于jquery性能最佳实践的讨论,与求教
2012/03/30 Javascript
javascript基础之查找元素的详细介绍(访问节点)
2013/07/05 Javascript
jquery 按钮状态效果 正常、移上、按下
2013/08/12 Javascript
jquery(hide方法)隐藏指定元素实例
2013/11/11 Javascript
js图片处理示例代码
2014/05/12 Javascript
JS中getYear()和getFullYear()区别分析
2014/07/04 Javascript
如何调试异步加载页面里包含的js文件
2014/10/30 Javascript
JavaScript限定图片显示大小的方法
2015/03/11 Javascript
JavaScript实现瀑布流布局
2020/06/28 Javascript
js/jq仿window文件夹移动/剪切/复制等操作代码
2017/03/08 Javascript
JavaScript实现的数字与字符串转换功能示例
2017/08/23 Javascript
微信小程序实现图片上传功能实例(前端+PHP后端)
2018/01/10 Javascript
JavaScript惰性求值的一种实现方法示例
2019/01/11 Javascript
Vue CLI3基础学习之pages构建多页应用
2019/06/02 Javascript
全面解析js中的原型,原型对象,原型链
2021/01/25 Javascript
[02:16]完美世界DOTA2联赛PWL S3 集锦第三期
2020/12/21 DOTA
python web框架学习笔记
2016/05/03 Python
使用Django Form解决表单数据无法动态刷新的两种方法
2017/07/14 Python
深入理解Python 关于supper 的 用法和原理
2018/02/28 Python
Python列表解析配合if else的方法
2018/06/23 Python
Pycharm 设置默认头的图文教程
2019/01/17 Python
深入理解Django-Signals信号量
2019/02/19 Python
Python 函数返回值的示例代码
2019/03/11 Python
python经典趣味24点游戏程序设计
2019/07/26 Python
Python通过cv2读取多个USB摄像头
2019/08/28 Python
Django Path转换器自定义及正则代码实例
2020/05/29 Python
汇集了世界上最好的天然和有机美容产品:LoveLula
2018/02/05 全球购物
焊接专业毕业生求职信
2013/10/01 职场文书
请假条标准格式规范
2014/04/10 职场文书
2014年服务行业工作总结
2014/11/18 职场文书
技术员岗位职责范本
2015/04/11 职场文书
领导干部学习三严三实心得体会
2016/01/05 职场文书
使用PDF.js渲染canvas实现预览pdf的效果示例
2021/04/17 Javascript
Django分页器的用法你都了解吗
2021/05/26 Python