2005年11月08日 星期二 15:50
各位,讨论一下Mixin机制吧,一下是我向limodou提问得到的关于Mixin 的一些解释,请各位添加几个小例子来具体说明一下这个东西可好? > Limodou,你好: > > 最近在看你的NewEdit源码,看到里面用到了Mixin机制,不甚明了,又到你的 > blog上找了一些资料来看,还是没有一个很清晰的概念,你这儿有这方面的资料 > 吗?能否介绍一些给我,谢谢! > > 恕冒昧, > > Arui. > 简单讲就是在运行时改变类。在我的blog和wiki上都有相关的mixin的说明。这种 做法只有象python这样的语言才可以做得到。那么它的好象是在开发和测试阶段, 你可以不断地扩展类,但不一定要修改原来的文件,而是通过mixin机制将相关的 修改放到其它的文件中,那么这个文件其实是一个功能的扩展集,它可能包含了许 多代码的修改,但程序代码却是可以放到一起。这样的做法使得扩展和修改都比起 以前的方式要方便得多。当然也有一些不好的地方,比如启动时有些慢(因此需要 一些优化的机制)。更多的内容我不太清楚你还有什么不太明白的,希望说得具体 一些。而且mixin技术只是一个统称,并没有一个标准的实现方法,象NewEdit中就 改造了多次,而且以后很有可能还会继续改造,主要是希望减少启动时的运行消 耗。因此你可以根据mixin的思想创造适合自已使用的mixin处理方式。 我想不外乎就是使用最基本的: 基类mixin,就是改造__base__,但NewEdit没有使用 改造属性和方法,使用setattr来向一个类动态地修改 创造自已的mixin框架,以便可以支持多类,可以方便地处理mixin 有什么不明白的再讨论吧。 未经limodou同意就把这个放上来,我想limodou不会介意吧? ^_^
2005年11月08日 星期二 16:15
在 05-11-8,Du Jun<jdu at haiercct.com.cn> 写道: > 各位,讨论一下Mixin机制吧,一下是我向limodou提问得到的关于Mixin 的一些解释,请各位添加几个小例子来具体说明一下这个东西可好? > > [snip]... > > 未经limodou同意就把这个放上来,我想limodou不会介意吧? 不会。 在NewEdit中Mixin是一个框架,相对复杂。在开发中面临的问题可能如下: * 多个类与相应的扩展对象 因此,每个可以扩展的类需要有一个寻找的机制,因此每个可以扩展的类在NewEdit我称之为slot class(槽类),都需要从Mixin基类派生,而且需要定义一个__mixinname__ 的名字。然后需要在__init__中执行self.initmixin() 而不同的扩展可以是常见的对象,如int, string, list, tuple, dict等,可以是方法,那么它们需要与不同的slot class相关联,但在关联之前需要有一个采集的过程。因此每个mixin对象在定义之后需要执行Mixin中的setPlugin或setMixin,主两个方法用于区分两种不同的mixin类型,同时是进行收集的工作。而且收集工作因为是在模块的顶层代码,因此在导入前会执行。要求就是:在slot class创建实现之间一定要完成mixin的收集工作。因此在真正的代码运行前的一些工作主要是环境的准备,包括导入所有mixin模块,执行收集的工作。 然后当类在创建实例时,由于必须调用self.initmixin(),这个方法非常重要,它装完成从收集的库中找到与类的__mixinname__对应的mixin对象,然后插入到类上,因此,NewEdit所使用的mixin是一种对类的扩展,并且在创建实例时,只完成一次的绑定工作,再创建这个类的其它实例时,这种绑定工作不会再次执行。 * mixin的执行细节 先要执行mixin对象的收集工作,然后再调用类初始化代码. * mixin的存储与定义 分为Mixin和Plugin,Mixin可以为大多数的对象,如int, string, tuple, list, dict, 方法等,它的作用为: class A:pass Mixin之后就变成: class A: a = 1 b = {} def p(self, name): print 相当于对类进行了扩展。对于象list, tuple, dict,NewEdit的Mixin模块还会进行合并,而不是简单的替换。 而plugin全部为方法,而且在使用时应该先在程序中设置一个调用点,所有针对这个调用点的方法会形成一个执行链,这里又分为两种:一种是顺序执行,不返回结果,链中所有的方法都会执行。另一种是有返回值,如果某个方法返回成功,则后续的方法不再执行,这种返回值结构为: flag, tuple flag 为True 或 False。为True表示后面的方法不再执行,False表示可以继续执行。tuple为真正的返回结果,它将返回给调用者。那么调用点的代码为: self.callplugin(args1, args2) 针对第一种无返回的调用 a = self.execplugin('init', args1, args2) 针对第二种有返回的调用,第一个参数是调用点的名字,将用于mixin对象的收集中。其它参数可以随便定义。 两种mixin对象的定义为: Mixin.setMixin('slotname', 'attributename', object, order=Mixin.Normal) Mixin.setPlugin('slotname', 'invokename', object, order=Mixin.Normal) 第一个参数为slot class 的mixin名 第二个参数,对于Mixin来说是绑定到槽类上的属性名,可以存在,可以不存在,对于Plugin来说是调用点的名字。order是实际的对象。order是表示在plugin链中的顺序。如果不定义就按导入时的顺序,在某些情况下你可能需要调整plugin的链结点顺序。 所有mixin对象在执行了setMixin()和setPlugin()之后会被收集到Mixin模块的全局变量中,它们按slot class的mixin名字来分组,然后再分为Mixin和Plugin两大类,然后进行排序。这些结果在NewEdit运行时会写在debug.txt文件中。 通过这些定义规则和执行要求,就把mixin与原始的类结合在一起,最终真正在运行时生成完整的类。因此,这种类在静态方式下看上去都是代码片段落,只有在运行时才是完整的。而且NewEdit的Mixin处理并不是一成不变的,它已经变化了多次,有可能还会变化。 -- I like python! My Blog: http://www.donews.net/limodou NewEdit Maillist: http://groups.google.com/group/NewEdit
2005年11月08日 星期二 17:20
弱弱地问一下,到底在什么时候才需要用到Mixin、plugin技术,有什么优点? 在 2005年11月8日 星期二 16:15,limodou 写道: > 在 05-11-8,Du Jun<jdu at haiercct.com.cn> 写道: > > > 各位,讨论一下Mixin机制吧,一下是我向limodou提问得到的关于Mixin 的一些解释,请各位添加几个小例子来具体说明一下这个东西可好? > > > > [snip]... > > > > 未经limodou同意就把这个放上来,我想limodou不会介意吧? > > 不会。 > > 在NewEdit中Mixin是一个框架,相对复杂。在开发中面临的问题可能如下: > > * 多个类与相应的扩展对象 > > 因此,每个可以扩展的类需要有一个寻找的机制,因此每个可以扩展的类在NewEdit我称之为slot > class(槽类),都需要从Mixin基类派生,而且需要定义一个__mixinname__ > 的名字。然后需要在__init__中执行self.initmixin() > > 而不同的扩展可以是常见的对象,如int, string, list, tuple, dict等,可以是方法,那么它们需要与不同的slot > class相关联,但在关联之前需要有一个采集的过程。因此每个mixin对象在定义之后需要执行Mixin中的setPlugin或setMixin,主两个 >方法用于区分两种不同的mixin类型,同时是进行收集的工作。而且收集工作因为是在模块的顶层代码,因此在导入前会执行。要求就是:在slot > class创建实现之间一定要完成mixin的收集工作。因此在真正的代码运行前的一些工作主要是环境的准备,包括导入所有mixin模块,执行收集的工作。 > > 然后当类在创建实例时,由于必须调用self.initmixin(),这个方法非常重要,它装完成从收集的库中找到与类的__mixinname__对应的m >ixin对象,然后插入到类上,因此,NewEdit所使用的mixin是一种对类的扩展,并且在创建实例时,只完成一次的绑定工作,再创建这个类的其它实例时, >这种绑定工作不会再次执行。 > > * mixin的执行细节 > > 先要执行mixin对象的收集工作,然后再调用类初始化代码. > > * mixin的存储与定义 > > 分为Mixin和Plugin,Mixin可以为大多数的对象,如int, string, tuple, list, dict, 方法等,它的作用为: > > class A:pass > > Mixin之后就变成: > > class A: > a = 1 > b = {} > def p(self, name): > print > > 相当于对类进行了扩展。对于象list, tuple, dict,NewEdit的Mixin模块还会进行合并,而不是简单的替换。 > > 而plugin全部为方法,而且在使用时应该先在程序中设置一个调用点,所有针对这个调用点的方法会形成一个执行链,这里又分为两种:一种是顺序执行,不返回结 >果,链中所有的方法都会执行。另一种是有返回值,如果某个方法返回成功,则后续的方法不再执行,这种返回值结构为: > > flag, tuple > > flag 为True 或 > False。为True表示后面的方法不再执行,False表示可以继续执行。tuple为真正的返回结果,它将返回给调用者。那么调用点的代码为: > > self.callplugin(args1, args2) 针对第一种无返回的调用 > a = self.execplugin('init', args1, args2) > 针对第二种有返回的调用,第一个参数是调用点的名字,将用于mixin对象的收集中。其它参数可以随便定义。 > > 两种mixin对象的定义为: > > Mixin.setMixin('slotname', 'attributename', object, order=Mixin.Normal) > Mixin.setPlugin('slotname', 'invokename', object, order=Mixin.Normal) > > 第一个参数为slot class 的mixin名 > 第二个参数,对于Mixin来说是绑定到槽类上的属性名,可以存在,可以不存在,对于Plugin来说是调用点的名字。order是实际的对象。order是表 >示在plugin链中的顺序。如果不定义就按导入时的顺序,在某些情况下你可能需要调整plugin的链结点顺序。 > > 所有mixin对象在执行了setMixin()和setPlugin()之后会被收集到Mixin模块的全局变量中,它们按slot > class的mixin名字来分组,然后再分为Mixin和Plugin两大类,然后进行排序。这些结果在NewEdit运行时会写在debug.txt文件中 >。 > > 通过这些定义规则和执行要求,就把mixin与原始的类结合在一起,最终真正在运行时生成完整的类。因此,这种类在静态方式下看上去都是代码片段落,只有在运行 >时才是完整的。而且NewEdit的Mixin处理并不是一成不变的,它已经变化了多次,有可能还会变化。 > > -- > I like python! > My Blog: http://www.donews.net/limodou > NewEdit Maillist: http://groups.google.com/group/NewEdit
2005年11月08日 星期二 20:42
在 05-11-8,amingsc<amingsc at 163.com> 写道: > 弱弱地问一下,到底在什么时候才需要用到Mixin、plugin技术,有什么优点? > 这种技术是自已选择的结果,也许你永远也用不上。我之所以选择这种技术来开发NewEdit,因为我知道NewEdit的开发是一个渐近的过程,那么如何在这个过程中方便地增加新的功能,方便地进行功能的隔离,而且可以选择某些功能的裁剪,基于这些想法使用Mixin是一种好的选择。而且在功能稳定之后,你完全可以将代码进行最终的合并,因为使用Mixin在运行时动态合成类在启动时会占用大量的时间。因此作为原型开发是一种好的方式。现在还没有想好,如何构造一种类似编译的技术,可以把Mixin的东西转成相对静态的东西。如果这个可以完成的话,程序编写时还是可以采用动态的Mixin方式来构造,然后通过一个生成过程合并成相对静态的代码,目的是提高运行速度,而且这一过程通过工具来保证,对于写程序没有什么影响。只不过这种想法不好实现。 因此,对于你如果不习惯或不需要这样的开发方式或功能,完全可以不用学习。Python就是这样,有些功能也许你几乎用不上,但对某些人来说可能会经常用,选择的范围很大。 -- I like python! My Blog: http://www.donews.net/limodou NewEdit Maillist: http://groups.google.com/group/NewEdit
2005年11月08日 星期二 23:58
终于可以发信了, 想问一下,是不是mixin的时候,当改变了一个类,然后申明了一个实例,然后又改变了这个类,那么这个时候这个实例是不是不会改变呢? 那么这个类这个时候是不是就没什么用了?
2005年11月09日 星期三 08:42
在 05-11-8,lof<flyli3415 at gmail.com> 写道: > 终于可以发信了, > 想问一下,是不是mixin的时候,当改变了一个类,然后申明了一个实例,然后又改变了这个类,那么这个时候这个实例是不是不会改变呢? > 那么这个类这个时候是不是就没什么用了? > 这个倒是不一定。如果你改变的是类的属性或方法,类本身的对象并不发生变化,这样实例中对于类的引用(__class__)也不会发生变化。完全可以做成类是动态改变,而不是一次改变,但那样的话调试及效率可能都是问题。不过,也许有适合的场合。 -- I like python! My Blog: http://www.donews.net/limodou NewEdit Maillist: http://groups.google.com/group/NewEdit
Zeuux © 2025
京ICP备05028076号