5

メッセージをデコードし、ユーザー コードにコールバックするイベント ディスパッチャー フレームワークを構築しています。私の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()しかし、andonBar()をメソッドとしてDispatcher配置し、ユーザーがそれらを他のメソッドに置き換えられるようにすることも想像できます。次に、ユーザーのコードは次のようになります。

def onFoo():
    do_something()

dispatcher = Dispatcher()
dispatcher.onFoo = onFoo

callable のリストを作成することもできるDispatcher.onFooので、ユーザーは C# のように複数のハンドラーをアタッチできます。

それを行うための最もPython的な方法は何ですか?

4

1 に答える 1

4

特に、実行時にオブジェクトを組織化された方法で (つまり、さまざまな種類のオブジェクトを渡すことによって)カスタマイズできるようにする場合は、最初の方法で行うことに特に問題があるとは言えません。複雑な状態と相互作用し、維持します。DispatcherHandlerHandler

Handlerしかし、基本クラスをこのように定義しても、実際には何も得られません。Handlerこれは抽象基本クラスではなく、通常の基本クラスであるため、クラスはメソッドをオーバーライドせずにサブクラス化できます。したがって、賢明なデフォルトの動作がいくつかある場合は、それらを に組み込むことをお勧めしHandlerます。そうしないと、ユーザーは何も得られません。Handler独自のHandlerクラスを定義することもできます。ただし、操作なしのプレースホルダーを提供するだけの場合は、このセットアップで問題ありません。

いずれにせよ、私はあなたが提案する2番目のアプローチよりも最初のアプローチを個人的に好みます。どちらがより「pythonic」であるかは定かではありませんが、最初のほうがロジックが分離されているため、よりクリーンなアプローチのように思えHandlerますDispatcher(一部のthreading.Threadメソッドのみを安全にオーバーライドできるような状況を回避できます。私はいつもそれが少し耳障りであることに気付きました。)

ただし、真正な抽象基底クラスが本当に必要な場合は、作成する必要があることを指摘しておく必要があると思います。2.6 の時点で、Python は多くの優れた機能を備えた柔軟な抽象基底クラスをサポートしています。たとえば、abstractmethodデコレーターを使用して抽象メソッドを定義できます。これにより、サブクラスによってオーバーライドされる必要があります。ただし、オーバーライドする必要のない通常のメソッドを定義することもできます。C++ イディオムの Pythonic バージョンを探している場合は、おそらくこれが最善の方法です。もちろん、同じではありませんが、現在のものよりも近いものになります。

于 2012-05-04T21:35:42.557 に答える