Created
January 18, 2023 16:53
-
-
Save clbarnes/785a36f389c5a409cbbc798ac46edebb to your computer and use it in GitHub Desktop.
functools.lru_cache wrapper which copies cached return values
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 functools import lru_cache, wraps | |
| from typing import Optional, Callable | |
| from copy import copy, deepcopy | |
| def copy_cache(deep: bool = True, maxsize: Optional[int] = 128, typed: bool = False): | |
| """Decorator factory wrapping functools.lru_cache, which copies return values. | |
| Use this for functions with mutable return values. | |
| N.B. must be called with parentheses. | |
| Parameters | |
| ---------- | |
| deep : bool, optional | |
| Whether to deepcopy return values, by default True | |
| maxsize : Optional[int], optional | |
| See lru_cache, by default 128. | |
| Use None for an unbounded cache (which is also faster). | |
| typed : bool, optional | |
| See lru_cache, by default False | |
| Returns | |
| ------- | |
| Callable[[Callable], Callable] | |
| Returns a decorator. | |
| Examples | |
| -------- | |
| >>> @copy_cache() # must include parentheses, unlike some zero-arg decorators | |
| ... def my_function(key: str, value: int) -> dict: | |
| ... return {key: value} | |
| ... | |
| >>> d1 = my_function("a", 1) | |
| >>> d1["b"] = 2 | |
| >>> d2 = my_function("a", 1) | |
| >>> "b" in d2 # would be True with raw functools.lru_cache | |
| False | |
| """ | |
| copier = deepcopy if deep else copy | |
| def wrapper(fn): | |
| wrapped = lru_cache(maxsize, typed)(fn) | |
| @wraps(fn) | |
| def copy_wrapped(*args, **kwargs): | |
| out = wrapped(*args, **kwargs) | |
| return copier(out) | |
| copy_wrapped.cache_info = wrapped.cache_info | |
| copy_wrapped.cache_clear = wrapped.cache_clear | |
| return copy_wrapped | |
| return wrapper |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment