7

I have 5 sets of request's categories defined as python dicts, for example:

category1 = {'type1', 'type2', 'type3'}
category2 = {'type4', 'type5'}
category3 = {'type6', 'type7', 'type8', 'type9'}
category4 = {'type10', 'type11'}
category5 = {'type12', 'type13', 'type14'}

And I need to handle requests using their category, for instance:

if request_type in category1:
    # process category1 request
    process_category1_request(...)
elif request_type in category2:
    # process category2 request
    process_category2_request(...)
elif...

and I need to dispatch a request using the request type to a different function to process it.

I already know there are ways of dispatching this requests in Python without the need of using if-elif, but my question is: what's the best way to do it while maintaining the code clean and simple?

4

5 に答える 5

16

request_type複数のカテゴリに存在する可能性がある場合は、タプルを使用してそれらを優先順位でループできます。

categories = (
    (category1, dispatch1method), 
    (category2, dispatch2method),
    (category3, dispatch3method),
    (category4, dispatch4method),
    (category5, dispatch5method),
)

next(method for cat, method in categories if request_type in cat)(arguments)

それ以外の場合は、代わりに a を使用しdict()てカテゴリ タイプをディスパッチ メソッドにマップします。上記と同じタプルオブタプルのマッピングを再利用して、ディスパッチを構築します。

category_dispatch = {}
for cat, dispatch in categories:
    category_dispatch.update(dict.fromkeys(cat.keys(), dispatch))

次に、そのリクエスト タイプを調べます。

category_dispatch[request_type](arguments)

このようなマッピング ルックアップは、一致が見つかるまで各カテゴリに対して順番にテストする必要があるタプルをスキャンするよりも高速です。

実際、次のように同じタプル構造を逆にすることで、優先順位を維持できます。

category_dispatch = {}
for cat, dispatch in reversed(categories):
    category_dispatch.update(dict.fromkeys(cat.keys(), dispatch))

request_typeこれ以降、特定のキーの最も優先度の高いマッピングがcategory_dispatch最後に構造体に入力されます。これにより、リクエスト タイプが複数のカテゴリに存在する場合でも、最速のディスパッチが得られます。

欠点は、マッピングが動的である場合(要求タイプが時間の経過とともにさまざまなカテゴリに追加および削除される)、それらの変更を反映するために dict をcategory*維持する必要があることです。category_dispatch

于 2013-01-10T17:15:39.557 に答える
4

コードを最も読みやすくするために、最もクリーンなのは 2 つのマップであると思います。

type_category_map = {"type1" : "category1", 
"type2" : "category1", , 
"type3" : "category1",
"type4" : "category2",
....
"type14" : "category5"}

category_function_map = {"category1" : "handler1_function",
"category2" : "handler2_function,
....
}

次に、pythonはこれです:

category = type_category_map[request_type]
handler_function = category_function_map[category]
handler_function(request)

単一のデータ構造でそれを行う方法はありますが、これほど明確で簡単に従う方法はないと思います。

于 2013-01-10T17:32:43.867 に答える
3

カテゴリをハンドラーにマップします。マップのサイズに関係なく、アクセス時間は O(1) になります。

MAP = {
  'cat1': handler1,
  'cat2': handler2,
   ....
}

MAP[request_type](...)
于 2013-01-10T17:15:46.753 に答える
3

次のようなdictを指定することはできません

カテゴリ1 = {'type1', 'type2', 'type3'}

ここには Key-Value がありません。

あなたの質問に関しては、簡単な解決策はあなたにとって良いですか?

dispatchers = {}

def register_dispatches(types, dispatcher):
    dispatchers.update(dict.fromkeys(types, dispatcher))

def process(request_type, *args, **kwargs):
    dispatchers[request_type](*args, **kwargs)


register_dispatches(['type1', 'type2', 'type3'], process_category1_request)
register_dispatches(['type4', 'type5'], process_category2_request)
...
process(request_type, ...)
于 2013-01-10T17:21:15.760 に答える
2
categories = {request1 : dispatch1, request2 : dispatch2, request3 : dispatch3}
for category, dispatch in categories.iteritems():
    if something in category:
        dispatch(something)

これはどう?

于 2013-01-10T17:15:35.780 に答える