gpt4 book ai didi

python - 将抽象类用于事件处理程序回调是惯用的 Python 吗?

转载 作者:太空狗 更新时间:2023-10-30 01:16:50 24 4
gpt4 key购买 nike

我正在构建一个事件调度程序框架,用于解码消息并回调到用户代码中。我的 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()

然后框架用户会写这样的东西:

class MyHandler(Handler):
def onFoo(self):
do_something()

dispatcher = Dispatcher()
myHandler = MyHandler()
dispatcher.handler = myHandler
dispatcher.run()

但我也可以想象将 onFoo()onBar() 作为 Dispatcher 的方法,让用户用其他方法替换它们.那么用户的代码将如下所示:

def onFoo():
do_something()

dispatcher = Dispatcher()
dispatcher.onFoo = onFoo

我还可以使 Dispatcher.onFoo 成为可调用列表,这样用户就可以像在 C# 中那样附加多个处理程序。

最符合 Pythonic 的方法是什么?

最佳答案

我不会说第一种方式有什么特别错误,特别是如果你想允许 Dispatcher 对象以有组织的方式定制运行时(即通过将不同类型的 Handler 对象传递给它们),如果您的 Handler 需要与复杂状态交互并保持复杂状态。

但是通过这种方式定义基类 Handler 并不能真正获得任何好处;一个类仍然可以子类化 Handler 而无需覆盖任何方法,因为这不是一个抽象基类——它只是一个常规基类。因此,如果有一些合理的默认行为,我建议将它们构建到 Handler 中。否则,您的用户根本不会从 Handler 中获得任何东西——他们还不如定义自己的 Handler 类。不过,如果您只想提供一个无操作占位符,那么此设置就可以了。

无论如何,我个人更喜欢第一种方法,而不是您建议的第二种方法;我不确定哪个更“pythonic”,但第一个对我来说似乎是一种更简洁的方法,因为它使 HandlerDispatcher 逻辑分开。 (它避免了像您在 threading.Thread 中看到的那样您只能安全地覆盖一些方法的情况——我一直觉得这有点不和谐。)

不过,我觉得我应该指出,如果你真的想要一个真正的抽象基类,你应该写一个!从 2.6 开始,Python 提供了对灵活 abstract base classes 的支持。有很多不错的功能。例如,您可以使用 abstractmethod 装饰器定义一个抽象方法,这确保它必须被子类覆盖;但您也可以定义不必重写的常规方法。如果您正在寻找 C++ 习语的 Pythonic 版本,这可能是最好的方法——当然,这不是一回事,但它比您现在拥有的更接近。

关于python - 将抽象类用于事件处理程序回调是惯用的 Python 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10456193/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com