I've written a decorator for easily creating multiple dispatch functions:
from functools import wraps def multi_dispatch(for_function): """ Returns a multiple dispatch version of the function. The returned function doesn't allow keyword arguments. >>> @multi_dispatch ... def foo(a, b): ... pass ... >>> @foo.add ... def _foo(a: int, b: int, c : str = '33'): ... return a + b*3 + len(c) ... >>> @foo.add ... def _foo(a: int, b: int, c = 3): ... return a + b*3 - c ... >>> @foo.add ... def _foo(a: float, b: float): ... return a*2 - b ... >>> foo(4, 5) 16 >>> foo(1.0, 2.0) 0.0 >>> foo(4, 5, 'loooong') 26 >>> foo(3, 4.5) Traceback (most recent call last): ... KeyError: (<class 'int'>, <class 'float'>) """ @wraps(for_function) def decorated(*args): return decorated.registry[tuple(type(i) for i in args)](*args) decorated.registry = {} def adder(func): """ Adds the supplied function to the multiple dispatch registry. """ code = func.__code__ args = code.co_varnames annotations = func.__annotations__ types = tuple(annotations[a] for a in args if a in annotations) decorated.registry[types] = func return func decorated.add = adder return decorated
I'd like to read your comments about the code (efficiency, re-usability, etc.), documentation and everything else that you feel is worth noting.
Update: After fixing all the points listed in the choosen answer, I have created a new version.