diff options
-rw-r--r-- | Doc/library/collections.rst | 48 |
1 files changed, 32 insertions, 16 deletions
diff --git a/Doc/library/collections.rst b/Doc/library/collections.rst index 2a0bc04..b1779a5 100644 --- a/Doc/library/collections.rst +++ b/Doc/library/collections.rst @@ -1171,27 +1171,43 @@ original insertion position is changed and moved to the end:: self.move_to_end(key) An :class:`OrderedDict` would also be useful for implementing -variants of :func:`functools.lru_cache`:: +variants of :func:`functools.lru_cache`: - class LRU(OrderedDict): - 'Limit size, evicting the least recently looked-up key when full' +.. testcode:: - def __init__(self, maxsize=128, /, *args, **kwds): - self.maxsize = maxsize - super().__init__(*args, **kwds) + class LRU: - def __getitem__(self, key): - value = super().__getitem__(key) - self.move_to_end(key) + def __init__(self, func, maxsize=128): + self.func = func + self.maxsize = maxsize + self.cache = OrderedDict() + + def __call__(self, *args): + if args in self.cache: + value = self.cache[args] + self.cache.move_to_end(args) + return value + value = self.func(*args) + if len(self.cache) >= self.maxsize: + self.cache.popitem(False) + self.cache[args] = value return value - def __setitem__(self, key, value): - if key in self: - self.move_to_end(key) - super().__setitem__(key, value) - if len(self) > self.maxsize: - oldest = next(iter(self)) - del self[oldest] +.. doctest:: + :hide: + + >>> def square(x): + ... return x ** 2 + ... + >>> s = LRU(square, maxsize=5) + >>> actual = [(s(x), s(x)) for x in range(20)] + >>> expected = [(x**2, x**2) for x in range(20)] + >>> actual == expected + True + >>> actual = list(s.cache.items()) + >>> expected = [((x,), x**2) for x in range(15, 20)] + >>> actual == expected + True :class:`UserDict` objects |