bpo-44782: Improve OrderedDict recipe for LRU cache variants (GH-27536) (GH-27567)

This commit is contained in:
Miss Islington (bot) 2021-08-02 11:37:42 -07:00 committed by GitHub
parent e0d599fa48
commit c50a672eeb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -1149,27 +1149,43 @@ original insertion position is changed and moved to the end::
self.move_to_end(key) self.move_to_end(key)
An :class:`OrderedDict` would also be useful for implementing An :class:`OrderedDict` would also be useful for implementing
variants of :func:`functools.lru_cache`:: variants of :func:`functools.lru_cache`:
class LRU(OrderedDict): .. testcode::
'Limit size, evicting the least recently looked-up key when full'
def __init__(self, maxsize=128, /, *args, **kwds): class LRU:
def __init__(self, func, maxsize=128):
self.func = func
self.maxsize = maxsize self.maxsize = maxsize
super().__init__(*args, **kwds) self.cache = OrderedDict()
def __getitem__(self, key): def __call__(self, *args):
value = super().__getitem__(key) if args in self.cache:
self.move_to_end(key) 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 return value
def __setitem__(self, key, value): .. doctest::
if key in self: :hide:
self.move_to_end(key)
super().__setitem__(key, value) >>> def square(x):
if len(self) > self.maxsize: ... return x ** 2
oldest = next(iter(self)) ...
del self[oldest] >>> 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 :class:`UserDict` objects