鱼C论坛

 找回密码
 立即注册
查看: 49435|回复: 126

[扩展阅读] Python Mixin 编程机制(转)

  [复制链接]
发表于 2014-6-28 21:16:18 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
Mixin 简介

Mixin 编程是一种开发模式,是一种将多个类中的功能单元的进行组合的利用的方式,这听起来就像是有类的继承机制就可以实现,然而这与传统的类继承有所不同。通常 Mixin 并不作为任何类的基类,也不关心与什么类一起使用,而是在运行时动态的同其他零散的类一起组合使用。


特点

使用 Mixin 机制有如下好处:

  • 可以在不修改任何源代码的情况下,对已有类进行扩展;
  • 可以保证组件的划分;
  • 可以根据需要,使用已有的功能进行组合,来实现“新”类;
  • 很好的避免了类继承的局限性,因为新的业务需要可能就需要创建新的子类。


多继承

Python支持多继承,即一个类可以继承多个子类。可以利用该特性,可以方便的实现mixin继承。如下代码,类A,B分别表示不同的功能单元,C为A,B功能的组合,这样类C就拥有了类A, B的功能。

  1. class A:
  2.     def get_a(self):
  3.         print('a')

  4. class B:
  5.     def get_b(self):
  6.         print('b')

  7. class C(A, B):
  8.         pass

  9. c = C()
  10. c.get_a()
  11. c.get_b()
复制代码


__bases__

多继承的实现就会创建新类,有时,我们在运行时,希望给类A添加类B的功能时,也可以利用python的元编程特性,__bases__属性便在运行时轻松给类A添加类B的特性,如下代码:
  1. A.__bases__ += (B,)
  2. a.get_b()
复制代码

其实__bases__也是继承的机制,因为__bases__属性存储了类的基类。因此多继承的方法也可以这样实现:
  1. class C:
  2.     pass

  3. C.__bases__ += (A, B, )
复制代码


插件方式

以上两种方式,都是基于多继承和python的元编程特性,然而在业务需求变化时,就需要新的功能组合,那么就需要重新修改A的基类,这回带来同步的问题,因为我们改的是类的特性,而不是对象的。因此以上修改会对所有引用该类的模块都收到影响,这是相当危险的。通常我们希望修改对象的行为,而不是修改类的。同样的我们可以利用__dict__来扩展对象的方法。

  1. class PlugIn(object):
  2.     def __init__(self):
  3.         self._exported_methods = []
  4.         
  5.     def plugin(self, owner):
  6.         for f in self._exported_methods:
  7.             owner.__dict__[f.__name__] = f

  8.     def plugout(self, owner):
  9.         for f in self._exported_methods:
  10.             del owner.__dict__[f.__name__]

  11. class AFeature(PlugIn):
  12.     def __init__(self):
  13.         super(AFeature, self).__init__()
  14.         self._exported_methods.append(self.get_a_value)

  15.     def get_a_value(self):
  16.         print('a feature.')

  17. class BFeature(PlugIn):
  18.     def __init__(self):
  19.         super(BFeature, self).__init__()
  20.         self._exported_methods.append(self.get_b_value)

  21.     def get_b_value(self):
  22.         print('b feature.')

  23. class Combine:pass

  24. c = Combine()
  25. AFeature().plugin(c)
  26. BFeature().plugin(c)

  27. c.get_a_value()
  28. c.get_b_value()
复制代码



评分

参与人数 10荣誉 +15 鱼币 +16 贡献 +10 收起 理由
Zhuct + 1
lp17863564 -2 最后插件部分有一些课上没有的,希望能讲得.
zcn123 -5 -5 -3 这是那年的代码
天马流星拳 + 4 + 4 + 2 不太明白
Vincentish + 5 + 5 + 3 感谢楼主无私奉献!
Sue96 + 3 + 3 + 3 Python好灵活!
soft.hunter + 3 + 2 + 1 小甲鱼,快点更新相关内容吧,期待中
冷稀饭 -1 代码该升级换代了, print 'a' 现在哪还有.
爱学习的懒懒君 + 5 + 5 + 3 棒棒,谢谢甲鱼老师的分享
Ruide + 1 merci.

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2014-7-15 18:52:42 | 显示全部楼层
一知半解:sad,继续努力
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

发表于 2014-7-25 14:46:42 | 显示全部楼层
黄种人 发表于 2014-7-15 18:52
一知半解,继续努力

有所收获
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2014-9-2 12:15:10 | 显示全部楼层
第3个,完全看不懂在写什么!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 6 反对 0

使用道具 举报

发表于 2015-1-6 08:38:16 | 显示全部楼层
用复合再好。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-2-11 09:04:16 | 显示全部楼层
感觉没看懂
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-3-8 07:39:01 | 显示全部楼层
第三个完全看不懂:sweat:
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 2 反对 0

使用道具 举报

发表于 2015-3-8 21:28:38 | 显示全部楼层
最后的没懂
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-3-20 00:39:07 | 显示全部楼层
大条鱼 发表于 2014-9-2 12:15
第3个,完全看不懂在写什么!

最后的就是,定义一个插入的类,用来将具体的对象插入进去,从而获得该类的所有方法。比如AFeature().plugin(c),就是说,AFeature里存储了一些方法,然后插入了c对象,这样c对象就获得了AFeature里的所有方法。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 5 反对 0

使用道具 举报

发表于 2015-8-3 16:04:30 | 显示全部楼层
本帖最后由 jiexinren 于 2015-8-3 16:32 编辑
  1. class A:
  2.     def pA(self):
  3.         print('我是A')

  4. class B:
  5.     def pB(self):
  6.         print('我是B')

  7. class C:
  8.     def c(self):
  9.         pass

  10. C.__bases__+=(A,B,)
复制代码

这个在我电脑上无法运行啊(3.4.3,64位版本)
Traceback (most recent call last):
  File "E:/桌面/jicheng.py", line 13, in <module>
    C.__bases__+=(A,B,)
TypeError: Cannot create a consistent method resolution
order (MRO) for bases A, object, B
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 12 反对 0

使用道具 举报

发表于 2015-8-20 16:06:19 | 显示全部楼层
Python 2下运行通过。。Python3下不行
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2015-9-17 20:47:51 | 显示全部楼层
看不懂,看来还得继续努力啊:sad
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-2-3 19:56:00 | 显示全部楼层
zhujy 发表于 2015-3-20 00:39
最后的就是,定义一个插入的类,用来将具体的对象插入进去,从而获得该类的所有方法。比如AFeature().plu ...

没有所有方法哦~
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-2-21 11:13:44 | 显示全部楼层
jiexinren 发表于 2015-8-3 16:04
这个在我电脑上无法运行啊(3.4.3,64位版本)
Traceback (most recent call last):
  File "E:/桌面/j ...

Python 3.x 中的类默认都是新式类, 在新式类中好像无法修改__bases__
以Python 2.x为例,分别定义旧式类和新式类,你会发现旧式类可以正常运行,但新式类不可以
  1. In [1]: class A: pass

  2. In [2]: class B: pass

  3. In [3]: class C: pass

  4. In [4]: C.__bases__ += (A, B)

  5. In [5]:

  6. In [5]: class D(object): pass

  7. In [6]: class E(object): pass  

  8. In [7]: class F(object): pass

  9. In [8]: F.__bases__ += (D, E)
  10. ---------------------------------------------------------------------------
  11. TypeError                                 Traceback (most recent call last)
  12. <ipython-input-8-ffd2704d005f> in <module>()
  13. ----> 1 F.__bases__ += (D, E)

  14. TypeError: Cannot create a consistent method resolution
  15. order (MRO) for bases object, E, D

  16. In [9]: F.__bases__ += (A, B)

  17. In [10]: F.__bases__ += (A, D)
  18. ---------------------------------------------------------------------------
  19. TypeError                                 Traceback (most recent call last)
  20. <ipython-input-10-c1e1d5bc638e> in <module>()
  21. ----> 1 F.__bases__ += (A, D)

  22. TypeError: duplicate base class A
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 3 反对 0

使用道具 举报

发表于 2016-3-7 17:09:51 | 显示全部楼层
A.__bases__ += (B,)语句报错,错误内容如下,我不知道是哪里错了
TypeError: Cannot create a consistent method resolution
order (MRO) for bases object, B
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-4-2 09:25:08 | 显示全部楼层
A.__bases__ += (B,)
Traceback (most recent call last):
  File "<pyshell#50>", line 1, in <module>
    A.__bases__ += (B,)
TypeError: Cannot create a consistent method resolution
order (MRO) for bases object, B
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-4-5 11:53:36 | 显示全部楼层
Python 3中报错:
Traceback (most recent call last):
  File "C:/Users/win7/PycharmProjects/pyTrain/XJY.py", line 187, in <module>
    B.__bases__ += (A,)
TypeError: Cannot create a consistent method resolution
order (MRO) for bases A, object
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

发表于 2016-4-18 22:15:42 | 显示全部楼层
受益匪浅啊
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-4-27 20:19:20 | 显示全部楼层
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2016-5-17 10:07:58 | 显示全部楼层
是python2的例子
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-4-19 22:20

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表