我正在构建一个事件调度器框架,它将消息和调用解码回用户代码。我的C++背景表明我写的是:
class Handler:
def onFoo(self):
pass
def onBar(self):
pass
class Dispatcher:
def __init__(self):
self.handler = Handler()
def run():
while True:
msg = decode_message() # magic
if msg == 'foo':
handler.onFoo()
if msg == 'bar':
handler.onBar()
然后,框架用户会写下如下内容:
^{pr2}$但是我也可以想象将onFoo()
和{Dispatcher
的方法,并让用户用其他方法替换它们。那么用户的代码将如下所示:
def onFoo():
do_something()
dispatcher = Dispatcher()
dispatcher.onFoo = onFoo
我还可以使Dispatcher.onFoo
成为一个可调用的列表,这样用户就可以像在C中那样附加多个处理程序。在
什么是最Python式的方法?在
我不会说第一种方法有什么特别的错误,特别是如果你想让
Dispatcher
对象在运行时以有组织的方式进行定制(即通过向它们传递不同种类的Handler
对象),如果你的Handler
需要与它们交互并保持复杂的状态。在但是这样定义基类
Handler
并不能真正获得任何好处;一个类仍然可以在不重写任何方法的情况下子类Handler
,因为这不是一个抽象基类,它只是一个常规基类。因此,如果有一些合理的默认行为,我建议将它们构建到Handler
。否则,您的用户根本不会从Handler
中获得任何好处,他们不妨定义自己的Handler
类。不过,如果您只想提供一个no-op占位符,那么这个设置就可以了。在无论如何,我个人更喜欢第一种方法而不是您建议的第二种方法;我不确定哪一种方法更“pythonic”,但是第一种方法对我来说似乎是一种更干净的方法,因为它将}逻辑分开。(它避免了您在
Handler
和{threading.Thread
中看到的那种情况,在这种情况下,您只能安全地重写一些我一直发现有点刺耳的方法。)我觉得我应该指出,如果你真的想要一个真正的抽象基类,你应该写一个!从2.6开始,Python提供了对flexible abstract base classes的支持,并提供了许多不错的功能。例如,您可以使用
abstractmethod
修饰符定义一个抽象方法,这确保它必须被子类重写;但是您也可以定义不必重写的常规方法。如果您正在寻找一个python版本的c++习惯用法,这可能是最好的方法它当然不是同一回事,但它比您现在拥有的更接近。在相关问题 更多 >
编程相关推荐