@@ -1171,27 +1171,43 @@ original insertion position is changed and moved to the end::
11711171 self.move_to_end(key)
11721172
11731173An :class: `OrderedDict ` would also be useful for implementing
1174- variants of :func: `functools.lru_cache `::
1174+ variants of :func: `functools.lru_cache `:
11751175
1176- class LRU(OrderedDict):
1177- 'Limit size, evicting the least recently looked-up key when full'
1176+ .. testcode ::
11781177
1179- def __init__(self, maxsize=128, /, *args, **kwds):
1180- self.maxsize = maxsize
1181- super().__init__(*args, **kwds)
1178+ class LRU:
11821179
1183- def __getitem__(self, key):
1184- value = super().__getitem__(key)
1185- self.move_to_end(key)
1180+ def __init__(self, func, maxsize=128):
1181+ self.func = func
1182+ self.maxsize = maxsize
1183+ self.cache = OrderedDict()
1184+
1185+ def __call__(self, *args):
1186+ if args in self.cache:
1187+ value = self.cache[args]
1188+ self.cache.move_to_end(args)
1189+ return value
1190+ value = self.func(*args)
1191+ if len(self.cache) >= self.maxsize:
1192+ self.cache.popitem(False)
1193+ self.cache[args] = value
11861194 return value
11871195
1188- def __setitem__(self, key, value):
1189- if key in self:
1190- self.move_to_end(key)
1191- super().__setitem__(key, value)
1192- if len(self) > self.maxsize:
1193- oldest = next(iter(self))
1194- del self[oldest]
1196+ .. doctest ::
1197+ :hide:
1198+
1199+ >>> def square (x ):
1200+ ... return x ** 2
1201+ ...
1202+ >>> s = LRU(square, maxsize = 5 )
1203+ >>> actual = [(s(x), s(x)) for x in range (20 )]
1204+ >>> expected = [(x** 2 , x** 2 ) for x in range (20 )]
1205+ >>> actual == expected
1206+ True
1207+ >>> actual = list (s.cache.items())
1208+ >>> expected = [((x,), x** 2 ) for x in range (15 , 20 )]
1209+ >>> actual == expected
1210+ True
11951211
11961212
11971213:class: `UserDict ` objects
0 commit comments