Per-instance lru_cache using wrapt - Graham Dumpleton
Briefly

Per-instance lru_cache using wrapt - Graham Dumpleton
wrapt.lru_cache is a helper that addresses issues when functools.lru_cache is applied to instance methods. functools.lru_cache caches return values keyed by arguments and uses a maximum cache size with identical eviction behavior. When used on methods, the standard library treats self as a normal argument, so it becomes part of the cache key. This causes a shared cache budget across instances, incorrect cache hits and misses, and cache growth tied to instance identity rather than method arguments. wrapt.lru_cache keeps the underlying caching implementation and passes keyword arguments through unchanged, while using wrapt’s decorator machinery to apply functools.lru_cache correctly for class methods.
"wrapt.lru_cache is not a replacement for functools.lru_cache. The actual caching is still done by the standard library implementation, all of its keyword arguments are passed straight through, and the eviction behaviour is identical. What wrapt.lru_cache adds is a thin layer on top, built using wrapt's decorator machinery, that fixes how the underlying functools.lru_cache is applied when the decorated function turns out to be a method on a class."
"functools.lru_cache is a small but very useful decorator. You wrap a function with it and the function's return values are remembered, keyed on the arguments, up to some maximum cache size. Repeat calls with the same arguments skip the function body and return the cached result. from functools import lru_cache @lru_cache(maxsize=128) def expensive(n): print("computing", n) return n * n expensive(2) expensive(2) expensive(3) Running this prints computing 2 and computing 3 once each."
"It is when you reach for the same decorator on an instance method that things start to go wrong. The standard library implementation has no concept of the wrapped function being a method, so it treats self as just another argument and includes it in the cache key. That single design choice causes three distinct problems. Problem 1: instances share a single cache budget from functools import lru_cache class Computer: @lru_cache(maxsize=2) def compute(self, x): return x * 2 a = Computer() b = Computer() a.compute(1) a.compute(2) b.compute(1) b.compute(2) print(a.compute.cache_info()) The cache is a single shared structure"
Read at Grahamdumpleton
Unable to calculate read time
[
|
]