Last active
May 30, 2020 04:41
-
-
Save salt-die/cf4fcb7f7ffc21a4d4729254e48c65ac to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from inspect import signature | |
class dynamicdict(dict): | |
def __init__(self, default_factory, **kwargs): | |
super().__init__(**kwargs) | |
self._default_factory = default_factory | |
def __missing__(self, key): | |
self[key] = self._default_factory(key) | |
return self[key] | |
class FuncStorage: | |
def __init__(self, name): | |
self.name = name | |
self.funcs = [] | |
def __call__(self, *args, **kwargs): | |
generic = None # If arguments bind to a function with no annotation we'll remember and move on | |
for func in self.funcs: | |
sig = signature(func) | |
try: | |
bound_arguments = sig.bind(*args, **kwargs).arguments | |
except TypeError: | |
continue | |
try: | |
ann = func.__annotations__ | |
except AttributeError: | |
generic = func | |
continue | |
if all(isinstance(bound_arguments[name], type_) for name, type_ in ann.items()): | |
return func(*args, **kwargs) | |
if generic: | |
return generic(*args, **kwargs) | |
raise ValueError("No registered function matches the annotation types") | |
def __repr__(self): | |
return f'overloaded function {self.name}' | |
_func_storage_by_name = dynamicdict(FuncStorage) | |
def overloaded(func): | |
func_storage = _func_storage_by_name[func.__name__] | |
func_storage.funcs.append(func) | |
return func_storage | |
@overloaded | |
def add(x: int, y: int): | |
return x + y | |
@overloaded | |
def add(x: str, y: str): | |
return x + y + '!' | |
@overloaded | |
def add(x: float, y): | |
return f'{x} is float, {y} is anything' |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment