槽类

一个槽类就是可以允许实现Mixin的类,也叫目标类。一个类成为槽类必须从Mixin类进行派生,需要定义一个__mixinname__的类属性,这个属性就是用来关联Mixin和Plugin与槽类的唯一标识。同时在槽类的构造函数__init__中需要调用self.initmixin()(它是Mixin类的一个方法) 。这样,当创建槽类的实例时,就会使用此方法将所有与此槽类相关的Mixin和Plugin与槽类进行融合,从而生成最终的类。此过程是对类本身,而非实例本身,并且通过内部机制可以保证只执行一次。因此一个槽类只有在运行时,并且在创建了一个实例时才会是真正完整的。这一些的实现都要感谢Python本身的动态特性。

Mixin部件

这里所讲的Mixin部件包括:将成为槽类的类成员方法的方法,和成为槽类的类属性的属性。每一个Mixin部件都要在实现完成后,调用Mixin 模块的setMixin方法来声明此Mixin部件将与哪一个槽类名进行融合、融合后的名称、及部件的对象实例。方法声明为:

setMixin(slot_class_name, binding_name, instance)
 
slot_class_name
为槽类名称,即对应的槽类的__mixinname__的值
binding_name
为融合后的名称
instance
为Mixin部件的对象

举例如:

def OnClick(win, event):
    print ‘Click Me’
    win.Close()
Mixin.setMixin(‘mainframe’, ‘OnClick’, OnClick)

槽类名为:’mainframe’

绑定后的名字为:’OnClick’,这样,当实现融合后,在槽类的类方法为:OnClick。你也可以改名,这里没有改动。如果有两个Mixin部件的融合名是相同的,对于:

  1. 类方法

    后融合的方法会替换前面融合的方法

  2. 属性

    根据属性的不同有不同的处理:

    1. 列表,tuple

      将新的内容增加到已经存在的内容之后

    2. 字典

      将新的内容与已经存在的内容进地合并,如果已经存在某个键,则新的值会替换旧的值

    3. 其它

      新值将替换旧值

Mixin部件实例:即为此模块中的OnClick对象

Plugin部件

在实现Plugin部件之前,应该在相应的类中加入调用点,即增加:self.callplugin()或self.execplugin()的调用。然后再在Mixin文件中定义相应的Plugin部件。callplugin和execplugin是Mixin模块的方法,两者很象,区别就是callplugin不处理返回值,而execplugin会处理返回值。Plugin部件均为方法或函数,而且一个调用点可以对应多个Plugin部件。

callplugin与execplugin

方法声明为:

callplugin(‘plugin_call_name’, *args, **kwargs)
execplugin(‘plugin_call_name’, *args, **kwargs)

可以看出,每一个调用点都有一个字符串定义的名字,然后是相应的参数。

这里先强调一点,所有plugin部件会自动根据槽类、plugin_call_name进行分类,同时还会根据执行setPlugin时指定的优先级进行排序。因此, plugin部件最终会组织为一棵森林,每棵对就是一个槽类,每个槽类有若干个调用点,每个调用点对应一个按优先级排序的列表,列表中的每一个元素就是一个plugin部件–方法。

对于callplugin,它会把调用点对应的方法列表中的所有方法排优先级顺序自动执行一遍,同时传入*args, **kwargs参数。如例子中为:

self.callplugin(‘init’, self)

plugin_call_name为’init’,传入参数为自身的实例对象: self。

对于execplugin,它也会按方法优先级进行处理:

  1. 取出一个方法,调用它,同时传入相应的参数
  2. 判断返回值,如果为假,则跳到第一步;如果为真,则结束,同时返回结果

因此,这时函数的返回值就非常重要了。如果某个处理对其它处理没有影响,那么你不用返回任何值(这时Python会返回None),或返回假值。如果某个处理执行后,不再允许其它的处理继续,则要返回一个真值。在它后面的所有函数都不会再进行处理了。这样优先级和返回值就要仔细地考虑与调整。

Plugin部件的定义

首先定义一个函数,它的参数与相应的调用点的参数一致。然后定义完毕后,调用setPlugin来声明此函数将与哪个槽类的,哪个调用点相绑定。 setPlugin的函数声明为:

setPlugin(slot_class_name, binding_name, instance, priority, nice)
slot_class_name
槽类名称。即为对应的槽类的__mixinname__的值
binding_name
绑定后的名称
instance
Plugin部件的对象实例
priority
在函数列表中的顺序值。因为相同槽类的相同调入点对应的Plugin部件会组织为一个函数的列表,因此这个值代表函数的排列顺序。但它是一个大概的级别,一共有三个级别:HIGH, MIDDLE, LOW。相同的级别排列序列是由执行setPlugin的顺序来决定的。缺省为MIDDLE。
nice
定义最终优先级数。priority定义了三级分类,它们会被处理为某个确定的优先级数:HIGH=100, MIDDL=500, LOW=900。而nice则是直接设定这个优先级数。此参数缺省为-1,表示未定义,如果它的值 >= 0,则一个Plugin部件的优先级将使用此nice值来确认,而不是使用priority来确定。因此,此参数与priority是互斥的,只能有一个生效。

为了定义一个Plugin部件的执行顺序,一种是使用优先级参数来设定,还有一种方法是设定多个调用点,将Plugin部件分派到不同的调用点上。由于调用点是有执行顺序的,因此也决定了Plugin部件在大的范围上的执行顺序。


1条评论

该日志第一篇评论

发表评论

评论也有版权!