使用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 相关文章推荐
pip 错误unused-command-line-argument-hard-error-in-future解决办法
Jun 01 Python
Python中模块string.py详解
Mar 12 Python
用十张图详解TensorFlow数据读取机制(附代码)
Feb 06 Python
Pycharm激活码激活两种快速方式(附最新激活码和插件)
Mar 12 Python
Selenium使用Chrome模拟手机浏览器方法解析
Apr 10 Python
基于Tensorflow的MNIST手写数字识别分类
Jun 17 Python
解决python中0x80072ee2错误的方法
Jul 19 Python
快速解释如何使用pandas的inplace参数的使用
Jul 23 Python
详解向scrapy中的spider传递参数的几种方法(2种)
Sep 28 Python
python批量生成条形码的示例
Oct 10 Python
学会用Python实现滑雪小游戏,再也不用去北海道啦
May 20 Python
Python实现滑雪小游戏
Sep 25 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对文件夹进行相关操作(遍历、计算大小)
2015/11/04 PHP
php简单实现批量上传图片的方法
2016/05/09 PHP
thinkPHP中钩子的两种配置调用方法详解
2016/11/11 PHP
POST一个JSON格式的数据给Restful服务实例详解
2017/04/07 PHP
网站页面自动跳转实现方法PHP、JSP(下)
2010/08/01 Javascript
在JavaScript中构建ArrayList示例代码
2014/09/17 Javascript
JS中的hasOwnProperty()、propertyIsEnumerable()和isPrototypeOf()
2016/08/11 Javascript
Angular2 多级注入器详解及实例
2016/10/30 Javascript
基于javascript的Form表单验证
2016/12/29 Javascript
jQuery+ajax的资源回收处理机制分析
2017/01/07 Javascript
jQuery使用zTree插件实现可拖拽的树示例
2017/09/23 jQuery
安装vue-cli的简易过程
2018/05/22 Javascript
node.js读取Excel数据(下载图片)的方法示例
2018/08/02 Javascript
vue.js2.0 实现better-scroll的滚动效果实例详解
2018/08/13 Javascript
新手入门js闭包学习过程解析
2019/10/08 Javascript
[01:03:00]DOTA2上海特级锦标赛A组败者赛 EHOME VS CDEC第一局
2016/02/25 DOTA
[01:05]主宰至宝剑心之遗
2017/03/16 DOTA
[00:17]天涯墨客一技能展示
2018/08/25 DOTA
python计算最小优先级队列代码分享
2013/12/18 Python
json跨域调用python的方法详解
2017/01/11 Python
Python常见工厂函数用法示例
2018/03/21 Python
Python堆排序原理与实现方法详解
2018/05/11 Python
在Python中字典根据多项规则排序的方法
2019/01/21 Python
详解PyQt5中textBrowser显示print语句输出的简单方法
2020/08/07 Python
举例详解CSS3中的Transition
2015/07/15 HTML / CSS
css3给背景图片加颜色遮罩的方法
2019/11/05 HTML / CSS
eBay瑞士购物网站:eBay.ch
2018/12/24 全球购物
KOHLER科勒美国官网:国际著名卫浴橱柜领先品牌
2020/06/27 全球购物
医院保洁服务方案
2014/06/11 职场文书
公司授权委托书样本
2014/09/15 职场文书
农村党支部书记司法四风问题对照检查材料
2014/09/26 职场文书
就业协议书盖章的注意事项
2014/09/28 职场文书
单位委托书格式范本
2014/09/29 职场文书
建议书格式
2015/02/04 职场文书
六年级作文之关于梦
2019/10/22 职场文书
使用php的mail()函数实现发送邮件功能
2021/06/03 PHP