在开发比较复杂的程序时,通常会采用基于事件的驱动逻辑,例如在 H5 项目中经常使用的 js-signal,那么在 Python 中有没有类似的处理方式呢?
这个 PyDispatcher 是目前找到一个比较好用的处理基于事件逻辑的工具,下面弄个简单的例子来说明:
global_data.py
SIGNAL_DO_BAR = 'signal-do-bar' SINGAL_DO_FOO = 'signal-do-foo' sender = object()
首先定义了一个 Global Data,用来存储一些全局可用的变量;SIGNAL_DO_BAR 和 SIGNAL_DO_FOO 分别是两个事件的名称;sender 后续供 dispather 使用。
my_class.py
class MyClass: def __init__(self, name): self.name = name def doBar(self, value): print(f'{self.name} do bar, value: {value}') def doFoo(self, value): print(f'{self.name} do foo, value: {value}')
定义了一个简单的 My Class,有 doBar 和 doFoo 两个简单的实例方法。
test.py
from pydispatch import dispatcher import global_data as GlobalData from my_class import MyClass myClass = MyClass('my-class') dispatcher.connect(myClass.doBar, GlobalData.SIGNAL_DO_BAR, GlobalData.sender) dispatcher.connect(myClass.doFoo, GlobalData.SINGAL_DO_FOO, GlobalData.sender) dispatcher.send(GlobalData.SIGNAL_DO_BAR, GlobalData.sender, '123') dispatcher.send(GlobalData.SINGAL_DO_FOO, GlobalData.sender, 456)
上面诠释了 dispatcher 的用法,主要是 connect 和 send 方法;但是这样写略显麻烦,所以参照之前 js-signal 的经验,有了第二种写法:
from pydispatch import dispatcher import global_data as GlobalData from my_class import MyClass myClass = MyClass('my-class') def handleGlobalData(e, value): if e == GlobalData.SIGNAL_DO_BAR: myClass.doBar(value) elif e == GlobalData.SINGAL_DO_FOO: myClass.doFoo(value) dispatcher.connect(receiver=handleGlobalData, signal=dispatcher.Any, sender=GlobalData.sender) dispatcher.send(signal=dispatcher.Any, sender=GlobalData.sender, e=GlobalData.SIGNAL_DO_BAR, value='123') dispatcher.send(dispatcher.Any, GlobalData.sender, GlobalData.SINGAL_DO_FOO, 456)
在第二种方法中,因为并不关心具体的 singal 是什么,所以 dispatcher 的 connect 和 send 中的 signal 参数都为 dispatcher.Any;然后 send 时,将具体的事件名称通过参数的形式发送。