import inspect import collections __all__ = ['signature', 'defop', 'overloaded', 'overload'] def make_signature(fn): return tuple(fn.__annotations__.get(arg, object) for arg in inspect.getfullargspec(fn)[0]) registry = {} class MultiMethod(object): def __init__(self, name): self.name = name self.typemap = {} def __call__(self, *args): types = tuple(arg.__class__ for arg in args) function = self.typemap.get(types) if function is None: raise TypeError("no match") return function(*args) def register(self, types, function): if types in self.typemap: raise TypeError("duplicate registration") self.typemap[types] = function def overload(fn): name = fn.__name__ mm = registry.get(name) if mm is None: mm = registry[name] = MultiMethod(name) types = make_signature(fn) mm.register(types, fn) def _wrap(*args): return mm(*args) return _wrap if __name__ == '__main__': @overload def foo(x:int, y:float): return 'int, float' @overload def foo(x:str, y:str): return 'str, str' print(foo(1, 2.0)) print(foo('abc', 'def'))