Skip to content

Instantly share code, notes, and snippets.

@frodo821
Created October 25, 2018 08:14
Show Gist options
  • Save frodo821/7c3c965dd3ee64db2d983a925053d187 to your computer and use it in GitHub Desktop.
Save frodo821/7c3c965dd3ee64db2d983a925053d187 to your computer and use it in GitHub Desktop.
Python overloading annotation
#-*-coding: utf-8;-*-
"""
Overloaded function for python
"""
from sys import _getframe as gf
from inspect import signature as sig, _ParameterKind as kind, _empty as empty
class _function:
def __init__(self, func):
self.fn = func
self.sig = sig(func)
self._signature = tuple(
(a.annotation, a.kind) if isinstance(a.annotation, type) else None
for a in self.sig.parameters.values())
def match(self, *args, **kwargs):
try:
bound = self.sig.bind(*args, **kwargs)
except TypeError:
return 0
priority = 1
for key, arg in bound.arguments.items():
param = self.sig.parameters[key]
if not isinstance(param.annotation, type) or param.annotation is empty:
continue
if not isinstance(arg, param.annotation):
return 0
priority += 1
return priority
def __eq__(self, other):
if not isinstance(other, type(self)):
raise NotImplementedError
return self._signature == other._signature
def __ne__(self, other):
if not isinstance(other, type(self)):
raise NotImplementedError
return self._signature != other._signature
def __call__(self, *args, **kwargs):
return self.fn(*args, **kwargs)
class _dispatcher:
def __init__(self):
self.__funcs = []
def append(self, fn):
fnc = _function(fn)
for f in self.__funcs:
if fnc == f:
raise TypeError(f"A function with signature {f.sig} is alredy defined.")
self.__funcs.append(fnc)
def __call__(self, *args, **kwargs):
guess = []
for f in self.__funcs:
p = f.match(*args, **kwargs)
if p == 0:
continue
guess.append((p, f))
if not guess:
raise TypeError("No function was matched to the argument.")
guess.sort(key=lambda x: x[0])
return guess[-1][1](*args, **kwargs)
def overload(fn):
name = fn.__name__
frame = gf(1)
if name not in frame.f_locals:
ol = _dispatcher()
else:
ol = frame.f_locals[name]
ol.append(fn)
return ol
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment