It's most useful when you're using some data you already have as the dictionary key. A usecase i had for this was a binary file parser with 10 types of event markers. It was originally coded with if/elif, but performance was a pretty big consideration. Using the event markers as keys to a dictionary dispatch improved performance by about 15% and made the code significantly more readable.
Match only just came out in Python 3.10, so it doesn't universally work. I think you implied that in your comment, so I wanted to add context for others.
My favorite way to implement this is with decorators. I used this to make a dispatch table for reading objects from a MySQL database.
(Yes I know I should be using UserDict below. You should too and don't subclass dict like I did.)
class FuncRegistry(dict):
"""Creates a registry of hashable objects to function mappings."""
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
def register_for(self, key: Hashable) -> Callable:
"""Decorator to register functions in the registry.
Parameters
key: Hashable
The key which should point to this function
Returns: Callable
Returns a decorator that registers the function to the key"""
def decorator(fn: Callable) -> Callable:
self[key] = fn
return fn
return decorator
qreg = FuncRegistry()
@qreg.register_for('foobr')
def handle_foobr(arg1, arg2):
# do something here then
return
qreg['foobr']('ooo its an arg', 'oh look another arg')
This is fun to play around and basically what Python does under the hood to implement classes. In Python2 it was even more obvious that classes are just fancy wrappers around a dict called, unsurprisingly, __dict__.
Note: this won't work in Python3 because the class.__dict__ becomes immutable at some point after declaring it, but the attribute name resolution stays the same. And it gets more interesting once you throw inheritance into the mix.