Skip to content

Instantly share code, notes, and snippets.

@pilifjed
Last active July 31, 2020 10:21
Show Gist options
  • Save pilifjed/b24873bd80e0ffd3a23bd5c4f246937b to your computer and use it in GitHub Desktop.
Save pilifjed/b24873bd80e0ffd3a23bd5c4f246937b to your computer and use it in GitHub Desktop.
from functools import partial
class FlexiblePartial:
def __init__(self, func, __varnames=None):
if not isinstance(func, partial):
self.__varnames = func.__code__.co_varnames
else:
self.__varnames = __varnames
self.func = partial(func)
def __call__(self, *args, **kwargs):
unspecified_varnames = self.__get_unspecified_varnames(args, kwargs)
if unspecified_varnames:
return FlexiblePartial(partial(self.func,*args, **kwargs), self.__varnames)
else:
return self.func(*args, **kwargs)
def __repr__(self):
type_ = type(self)
brace_pos = str(self.func).find('(')
return (
"{module}.{name}{partial_repr_part}"
.format(
module=type_.__module__,
name=type_.__qualname__,
partial_repr_part=str(self.func)[brace_pos:]
)
)
def __get_unspecified_varnames(self, args, kwargs):
full_argct = len(self.func.args) + len(args)
full_argnames = set(self.__varnames[:full_argct])
full_kwargnames = set(partial(self.func, a=3).keywords.keys()) | set(kwargs.keys())
unspecified_varnames = set(self.__varnames) ^ (full_argnames | full_kwargnames)
return unspecified_varnames
##EXAMPLE
@FlexiblePartial
def add_(a, b, c):
return a + b + c
print(add_)
# __main__.FlexiblePartial(<function add_ at 0x0000000004BCFD08>)
add_23 = add_(2, c=3)
print(add_23)
# __main__.FlexiblePartial(<function add_ at 0x0000000004BCFD08>, 2, c=3)
print(add_23(4))
# 9
print(add_(2)(3,4))
# 9
print(add_(2,3)(4))
# 9
print(add_(2)(3)(4))
# 9
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment