Python Mixin 编程机制(转)
Mixin 简介Mixin 编程是一种开发模式,是一种将多个类中的功能单元的进行组合的利用的方式,这听起来就像是有类的继承机制就可以实现,然而这与传统的类继承有所不同。通常 Mixin 并不作为任何类的基类,也不关心与什么类一起使用,而是在运行时动态的同其他零散的类一起组合使用。
特点
使用 Mixin 机制有如下好处:
[*]可以在不修改任何源代码的情况下,对已有类进行扩展;
[*]可以保证组件的划分;
[*]可以根据需要,使用已有的功能进行组合,来实现“新”类;
[*]很好的避免了类继承的局限性,因为新的业务需要可能就需要创建新的子类。
多继承
Python支持多继承,即一个类可以继承多个子类。可以利用该特性,可以方便的实现mixin继承。如下代码,类A,B分别表示不同的功能单元,C为A,B功能的组合,这样类C就拥有了类A, B的功能。
class A:
def get_a(self):
print('a')
class B:
def get_b(self):
print('b')
class C(A, B):
pass
c = C()
c.get_a()
c.get_b()
__bases__
多继承的实现就会创建新类,有时,我们在运行时,希望给类A添加类B的功能时,也可以利用python的元编程特性,__bases__属性便在运行时轻松给类A添加类B的特性,如下代码:
A.__bases__ += (B,)
a.get_b()
其实__bases__也是继承的机制,因为__bases__属性存储了类的基类。因此多继承的方法也可以这样实现:
class C:
pass
C.__bases__ += (A, B, )
插件方式
以上两种方式,都是基于多继承和python的元编程特性,然而在业务需求变化时,就需要新的功能组合,那么就需要重新修改A的基类,这回带来同步的问题,因为我们改的是类的特性,而不是对象的。因此以上修改会对所有引用该类的模块都收到影响,这是相当危险的。通常我们希望修改对象的行为,而不是修改类的。同样的我们可以利用__dict__来扩展对象的方法。
class PlugIn(object):
def __init__(self):
self._exported_methods = []
def plugin(self, owner):
for f in self._exported_methods:
owner.__dict__ = f
def plugout(self, owner):
for f in self._exported_methods:
del owner.__dict__
class AFeature(PlugIn):
def __init__(self):
super(AFeature, self).__init__()
self._exported_methods.append(self.get_a_value)
def get_a_value(self):
print('a feature.')
class BFeature(PlugIn):
def __init__(self):
super(BFeature, self).__init__()
self._exported_methods.append(self.get_b_value)
def get_b_value(self):
print('b feature.')
class Combine:pass
c = Combine()
AFeature().plugin(c)
BFeature().plugin(c)
c.get_a_value()
c.get_b_value()
一知半解:sad,继续努力 黄种人 发表于 2014-7-15 18:52
一知半解,继续努力
有所收获 第3个,完全看不懂在写什么! 用复合再好。 感觉没看懂 第三个完全看不懂:sweat: 最后的没懂 大条鱼 发表于 2014-9-2 12:15
第3个,完全看不懂在写什么!
最后的就是,定义一个插入的类,用来将具体的对象插入进去,从而获得该类的所有方法。比如AFeature().plugin(c),就是说,AFeature里存储了一些方法,然后插入了c对象,这样c对象就获得了AFeature里的所有方法。 本帖最后由 jiexinren 于 2015-8-3 16:32 编辑
class A:
def pA(self):
print('我是A')
class B:
def pB(self):
print('我是B')
class C:
def c(self):
pass
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 Python 2下运行通过。。Python3下不行 看不懂,看来还得继续努力啊:sad zhujy 发表于 2015-3-20 00:39
最后的就是,定义一个插入的类,用来将具体的对象插入进去,从而获得该类的所有方法。比如AFeature().plu ...
没有所有方法哦~ 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为例,分别定义旧式类和新式类,你会发现旧式类可以正常运行,但新式类不可以
In : class A: pass
In : class B: pass
In : class C: pass
In : C.__bases__ += (A, B)
In :
In : class D(object): pass
In : class E(object): pass
In : class F(object): pass
In : F.__bases__ += (D, E)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-8-ffd2704d005f> in <module>()
----> 1 F.__bases__ += (D, E)
TypeError: Cannot create a consistent method resolution
order (MRO) for bases object, E, D
In : F.__bases__ += (A, B)
In : F.__bases__ += (A, D)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-10-c1e1d5bc638e> in <module>()
----> 1 F.__bases__ += (A, D)
TypeError: duplicate base class A
A.__bases__ += (B,)语句报错,错误内容如下,我不知道是哪里错了
TypeError: Cannot create a consistent method resolution
order (MRO) for bases object, B 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 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 {:10_266:}受益匪浅啊 {:5_91:} 是python2的例子