|
1 | | -def single_cache(f): |
| 1 | +"""Common caching methods, using `lru_cache` sometimes has its downsides.""" |
| 2 | +from functools import wraps, lru_cache |
| 3 | +import weakref |
| 4 | + |
| 5 | + |
| 6 | +def single_cache(func): |
| 7 | + """Cache with size 1.""" |
2 | 8 | last_args = () |
3 | 9 | last_kwargs = set() |
4 | 10 | last_result = None |
5 | 11 |
|
6 | | - def cached(*args, **kwargs): |
| 12 | + @wraps(func) |
| 13 | + def _cached(*args, **kwargs): |
7 | 14 | nonlocal last_args, last_kwargs, last_result |
8 | 15 | if len(last_args) != len(args) or \ |
9 | 16 | not all(x is y for x, y in zip(args, last_args)) or \ |
10 | 17 | last_kwargs != set(kwargs) or \ |
11 | 18 | any(last_kwargs[k] != kwargs[k] for k in last_kwargs): |
12 | | - last_result = f(*args, **kwargs) |
| 19 | + last_result = func(*args, **kwargs) |
13 | 20 | last_args, last_kwargs = args, kwargs |
14 | 21 | return last_result |
15 | 22 |
|
16 | | - return cached |
| 23 | + return _cached |
| 24 | + |
| 25 | + |
| 26 | +def memoize_method(*lru_args, **lru_kwargs): |
| 27 | + """Memoize methods without keeping reference to `self`. |
| 28 | +
|
| 29 | + Parameters |
| 30 | + ---------- |
| 31 | + lru_args |
| 32 | + lru_kwargs |
| 33 | +
|
| 34 | + Returns |
| 35 | + ------- |
| 36 | +
|
| 37 | + See Also |
| 38 | + -------- |
| 39 | + https://stackoverflow.com/questions/33672412/python-functools-lru-cache-with-class-methods-release-object |
| 40 | +
|
| 41 | + """ |
| 42 | + def _decorator(func): |
| 43 | + |
| 44 | + @wraps(func) |
| 45 | + def _wrapped_func(self, *args, **kwargs): |
| 46 | + self_weak = weakref.ref(self) |
| 47 | + # We're storing the wrapped method inside the instance. If we had |
| 48 | + # a strong reference to self the instance would never die. |
| 49 | + |
| 50 | + @wraps(func) |
| 51 | + @lru_cache(*lru_args, **lru_kwargs) |
| 52 | + def _cached_method(*args, **kwargs): |
| 53 | + return func(self_weak(), *args, **kwargs) |
| 54 | + |
| 55 | + setattr(self, func.__name__, _cached_method) |
| 56 | + return _cached_method(*args, **kwargs) |
| 57 | + |
| 58 | + return _wrapped_func |
| 59 | + |
| 60 | + return _decorator |
0 commit comments