使用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使用正则表达式过滤或替换HTML标签的方法详解
Sep 25 Python
Python如何生成树形图案
Jan 03 Python
python监控文件并且发送告警邮件
Jun 21 Python
python实现图片转字符小工具
Apr 30 Python
python 根据字典的键值进行排序的方法
Jul 24 Python
如何关掉pycharm中的python console(图解)
Oct 31 Python
Keras使用tensorboard显示训练过程的实例
Feb 15 Python
新手入门学习python Numpy基础操作
Mar 02 Python
python如何实现图片压缩
Sep 11 Python
使用OpenCV实现人脸图像卡通化的示例代码
Jan 15 Python
分析Python感知线程状态的解决方案之Event与信号量
Jun 16 Python
Python内置类型集合set和frozenset的使用详解
Apr 26 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
解析PayPal支付接口的PHP开发方式
2010/11/28 PHP
php数据入库前清理 注意php intval与mysql的int取值范围不同
2010/12/12 PHP
PHP优于Node.js的五大理由分享
2012/09/15 PHP
ThinkPHP中redirect用法分析
2014/12/05 PHP
PHP微信红包API接口
2015/12/05 PHP
PHP实现上传多文件示例代码
2017/02/20 PHP
Thinkphp实现站点静态化的方法详解
2017/03/21 PHP
JavaScript 在线压缩和格式化收藏
2009/01/16 Javascript
js 返回时间戳所对应的具体时间
2010/07/20 Javascript
非阻塞动态加载javascript广告实现代码
2010/11/17 Javascript
apycom出品的jQuery精美菜单破解方法
2011/02/18 Javascript
关闭时刷新父窗口两种方法
2014/05/07 Javascript
javascript实现获取服务器时间
2015/05/19 Javascript
jQuery实现Flash效果上下翻动的中英文导航菜单代码
2015/09/22 Javascript
详解angular中如何监控dom渲染完毕
2017/01/03 Javascript
完美解决axios跨域请求出错的问题
2018/02/05 Javascript
Layui给数据表格动态添加一行并跳转到添加行所在页的方法
2018/08/20 Javascript
vue+VeeValidate 校验范围实例详解(部分校验,全部校验)
2018/10/19 Javascript
vue实现的请求服务器端API接口示例
2019/05/25 Javascript
详解vue父子组件关于模态框状态的绑定方案
2019/06/05 Javascript
微信小程序工具函数封装
2019/10/28 Javascript
[01:01:52]DOTA2-DPC中国联赛定级赛 SAG vs iG BO3第二场 1月9日
2021/03/11 DOTA
[45:17]DOTA2-DPC中国联赛定级赛 Phoenix vs DLG BO3第三场 1月9日
2021/03/11 DOTA
微信跳一跳游戏python脚本
2020/04/01 Python
python-itchat 获取微信群用户信息的实例
2019/02/21 Python
基于python的BP神经网络及异或实现过程解析
2019/09/30 Python
python实现矩阵和array数组之间的转换
2019/11/29 Python
浅析python实现动态规划背包问题
2020/12/31 Python
如何用border-image实现文字气泡边框的示例代码
2020/01/21 HTML / CSS
马来西亚网上美容店:Hermo.my
2017/11/25 全球购物
《北京的春节》教学反思
2014/04/07 职场文书
项目申报专员岗位职责
2014/07/09 职场文书
项目委托协议书(最新)
2014/09/13 职场文书
亮剑观后感
2015/06/05 职场文书
请求模块urllib之PYTHON爬虫的基本使用
2022/04/08 Python
javascript进阶篇深拷贝实现的四种方式
2022/07/07 Javascript