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?
If request_type
can be present in more than one category, you could use a tuple to loop through them in priority order:
categories = (
(category1, dispatch1method),
(category2, dispatch2method),
(category3, dispatch3method),
(category4, dispatch4method),
(category5, dispatch5method),
)
next(method for cat, method in categories if request_type in cat)(arguments)
Otherwise use a dict()
to map category types to dispatch methods instead; reusing the same tuple-of-tuples mapping above to build a dispatch:
category_dispatch = {}
for cat, dispatch in categories:
category_dispatch.update(dict.fromkeys(cat.keys(), dispatch))
Then just look up the request type on that:
category_dispatch[request_type](arguments)
A mapping lookup like that would be faster than a scan through the tuple, where we have to test against each category in turn until we find a match.
In fact, the priority ordering can be maintained by reversing that same tuple structure like so:
category_dispatch = {}
for cat, dispatch in reversed(categories):
category_dispatch.update(dict.fromkeys(cat.keys(), dispatch))
since now the highest priority mapping for a given request_type
key will be entered into the category_dispatch
structure last. This will give you the fastest dispatch even if request types were present in multiple categories.
Disadvantage is that if your category*
mappings are dynamic (request types get added to and removed from different categories over time) you'd need to maintain the category_dispatch
dict to reflect those changes too.
I think the cleanest may be two maps, to make the code most readable.
type_category_map = {"type1" : "category1",
"type2" : "category1", ,
"type3" : "category1",
"type4" : "category2",
....
"type14" : "category5"}
category_function_map = {"category1" : "handler1_function",
"category2" : "handler2_function,
....
}
Then the python is just this:
category = type_category_map[request_type]
handler_function = category_function_map[category]
handler_function(request)
There would be ways to do it with a single data structure, but none that would be as clear and easy to follow as this, I think.
Map your categories to a handler. Independent of the size of the map you will have O(1) access time.
MAP = {
'cat1': handler1,
'cat2': handler2,
....
}
MAP[request_type](...)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With