鱼C论坛

 找回密码
 立即注册
楼主: 小甲鱼

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

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

使用道具 举报

发表于 2016-5-26 15:21:28 | 显示全部楼层
谢谢分享。。。。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-5-30 10:03:33 | 显示全部楼层
没看懂。。。最后一个写的是啥啊。。。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-6-8 13:22:20 | 显示全部楼层
似懂非懂ing
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-6-29 11:31:51 | 显示全部楼层
小甲鱼老师,能不能详细讲一下 插件方式 的用法啊?代码看不懂尼
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-7-6 10:25:48 | 显示全部楼层
学习了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-7-8 11:54:04 | 显示全部楼层
Mixin机制貌似就是通过修改对象的__dict__属性来添加或删除属性和方法

第三段的super()没看懂,是为了解决菱形继承?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-8-13 20:46:10 | 显示全部楼层
受益匪浅,谢谢楼主,说最后看不懂的同学可以慢慢理解下,拿AFeature来说,原理就是把AFeature的get_a_value方法的   对象(为了方便叫做a对象 吧)     给了 c对象,具体怎么给就是:c对象的__dict__[a.name]=a

意思就是说,c对象一提到a对象的名字:get_a_value,就给c对象一个a对象。

如果有什么不对欢迎指正
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-8-15 21:29:14 | 显示全部楼层
本帖最后由 van314159 于 2016-8-15 21:41 编辑

首先定义了一个能给对象添加方法的类(PlugIn),具体添加的方法是plugin函数, 即这一句
owner.__dict__[f.__name__] = f
owner就是类对象,也就是下面的c
接着定义了两个用作例子的类 AFeature BFeature, 它们都是Plugin 的子类,所以它们都有plugin方法.
其中AFeature中的
 self._exported_methods.append(self.get_a_value)
就是将AFeature 的方法 贮存到一个列表中,以备plugin或者plugout函数的使用。
最后就是
AFeature().plugin(c)
将c这个实例对象作为参数传入 plugin函数,然后给c添加AFeature的方法。 同时 类Combine 还没有受到影响。

PS. 代码中的 super函数的写法是不是 python2.7的写法? 只写 super().__init__() ,我试了也是可以的。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 4 反对 0

使用道具 举报

发表于 2016-10-14 17:13:38 | 显示全部楼层
原来如此。
class PlugIn(object):
    def __init__(self):
        self._exported_methods = []
        
    def plugin(self, owner):
        i = 0
        for f in self._exported_methods:
            owner.__dict__[f.__name__] = f
            i += 1
            print(f,i)
            

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

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()


结果:
>>>
RESTART: C:/Users/Administrator/AppData/Local/Programs/Python/Python35-32/7.py
<bound method AFeature.get_a_value of <__main__.AFeature object at 0x0219A070>> 1
<bound method BFeature.get_b_value of <__main__.BFeature object at 0x01B976B0>> 1
a feature.
b feature.
>>>
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-11-18 15:56:12 | 显示全部楼层
看不懂。。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-12-25 23:49:39 | 显示全部楼层

    AFeature().plugin(c)
  File "mixin.py", line 18, in __init__
    self._exported_methods.append(self.get_a_value)
AttributeError: 'AFeature' object has no attribute '_exported_methods'


为什么我报这个错误, 代码一样的
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-1-5 19:22:49 | 显示全部楼层
完全没看懂,说是说Mixn机制,可例子中完全没看到Mixin字样。网上有这样的例子:
class Dog(Mammal, RunnableMixin, CarnivorousMixin):
    pass


可否能用这类例子来解释一下,为什么要用Mixin,是不是只是一种习惯或规范,其实完全可以:
class Dog(Mammal, Runnable, Carnivorous):
    pass
对不对,只要编写的时候自己注意。

还是后面带了Mixin关键字,冲突方法会被Python解释器自动忽略
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-3-9 23:19:09 | 显示全部楼层
class PlugIn(object):
    def __init__(self):
        self._exported_methods = []    #初始化 输出的方法
        
    def plugin(self, owner):
        for f in self._exported_methods:   #对每一个输出的方法 在字典里扩充
            owner.__dict__[f.__name__] = f

    def plugout(self, owner):
        for f in self._exported_methods:    #去掉输出的方法
            del owner.__dict__[f.__name__]  

class AFeature(PlugIn):
#继承 插件  必须由PlugIn 否者报错[super() argument 1 must be type, not classobj]
    def __init__(self):
        super(AFeature, self).__init__()
#格式就是如此 也可以删掉super()括号中的内容
'''super(AFeature, self).__init__() :super(AFeature, self)
首先找到AFeature的父类(就是类PlugIn)
,然后把类AFeature的对象self转换为类PlugIn的对象
然后“被转换”的类PlugIn对象调用自己的__init__函数。'''
        self._exported_methods.append(self.get_a_value)
#这里直接将PlugIn的sel._exported_methods 移过来!
#self.get_a_value 不能去掉self, 这个函数也需要self来指向。

#通过AFeature().plugin(c) 将 get_a_value存入字典中 形式为c.get_a_value(owner.__dict__[f.__name__])
#c.get_a_value = self.get_b_value     这时候的self B->A , 调用就可以A调用B的 self.get_b_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)  
#将AB 中的方法 像“插件”的形式插入到c中。
c.get_a_value()
c.get_b_value()

'''  
    1. super并不是一个函数,是一个类名,形如super(B, self)事实上调用了super类的初始化函数,
       产生了一个super对象;
    2. super类的初始化函数并没有做什么特殊的操作,只是简单记录了类类型和具体实例;
    3. super(B, self).func的调用并不是用于调用当前类的父类的func函数;
    4. Python的多继承类是通过mro的方式来保证各个父类的函数被逐一调用,而且保证每个父类函数
       只调用一次(如果每个类都使用super);
    5. 混用super类和非绑定的函数是一个危险行为,这可能导致应该调用的父类函数没有调用或者一
       个父类函数被调用多次。'''
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

发表于 2017-3-29 11:55:27 | 显示全部楼层
其实从AFeature类开始理解应好理解一点,当u类实例化时,那么就进入__init__,则会有super(AFeaTure,self).__init__()这句代码执行,那么AFeature类就会得到一个_exported_methods的属性(因为继承自PlugIn).然后下一句就是把get_a_value这个方法存到列表中去待用。然后当AFeature实例化完毕后也会有基类的plugin方法,然后将c赋值进去时,c就是那个owner,然后就会owner.__dict__[f.__name__] = f这一句来把get_a_value保存给c。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

我的一样,根本无法运行
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-4-24 10:32:10 | 显示全部楼层
e,看得不是很懂
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

我的也运行不了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-7-25 14:39:09 | 显示全部楼层
最后一个一知半解。。。还是多看几遍吧,,,
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-7-27 13:53:35 | 显示全部楼层
f.__name__是啥意思呀。。哪位帮忙解释下。。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-12-22 13:00

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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