Last active
October 26, 2022 22:44
-
-
Save d3dave/f18d1750a5b8675e371c43dfcdd6470a to your computer and use it in GitHub Desktop.
cache_args
This file contains 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
# License: MIT | |
# Copyright (c) David D. Dorfman 2022 | |
""" | |
Cache function arguments from callables on first invocation | |
""" | |
from functools import partial, wraps | |
from typing import Any, Callable, Optional, ParamSpec, TypeVar | |
P = ParamSpec('P') | |
R = TypeVar('R') | |
def cache_args(*positional_gets: Callable[[], Any], **kwargs_gets: Callable[[], Any]): | |
""" | |
Compute values for the specified args on first invocation of the function and cache them for future calls. | |
Cached positional args cannot be overridden. Caching keyword args is akin to caching default values. | |
""" | |
def decorate(func: Callable) -> Callable: | |
partial_func: Optional[partial[R]] = None | |
def wrapper(*args, **kwargs) -> R: | |
nonlocal partial_func | |
if partial_func is None: | |
partial_args = [get_arg() for get_arg in positional_gets] | |
partial_kwargs = {kwarg: get_kwargs() for kwarg, get_kwargs in kwargs_gets.items()} | |
partial_func = partial(func, *partial_args, **partial_kwargs) | |
partial_func = wraps(func)(partial_func) | |
return partial_func(*args, **kwargs) | |
return wrapper | |
return decorate | |
# Example: | |
import platform | |
import distro | |
@cache_args(platform.machine, c=distro.id) | |
def f(a, b, *, c, d): | |
print(f'{a=} {b=} {c=} {d=}') | |
f('xyz', d='abc') | |
# a='x86_64' b='xyz' c='darwin' d='abc' |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment