lrucache.py 1.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
  1. class _NotFound:
  2. pass
  3. class LRUCache:
  4. def __init__(self, capacity, dispose):
  5. self._cache = {}
  6. self._lru = []
  7. self._capacity = capacity
  8. self._dispose = dispose
  9. def __setitem__(self, key, value):
  10. assert key not in self._cache, (
  11. "Unexpected attempt to replace a cached item,"
  12. " without first deleting the old item.")
  13. self._lru.append(key)
  14. while len(self._lru) > self._capacity:
  15. del self[self._lru[0]]
  16. self._cache[key] = value
  17. def __getitem__(self, key):
  18. try:
  19. self._lru.remove(key)
  20. self._lru.append(key)
  21. except ValueError:
  22. pass
  23. return self._cache[key]
  24. def __delitem__(self, key):
  25. try:
  26. self._lru.remove(key)
  27. except ValueError:
  28. pass
  29. item = self._cache.pop(key, _NotFound)
  30. if item is _NotFound:
  31. raise KeyError(key)
  32. self._dispose(item)
  33. def __contains__(self, key):
  34. return key in self._cache
  35. def clear(self):
  36. for value in self._cache.values():
  37. self._dispose(value)
  38. self._cache.clear()
  39. # useful for testing
  40. def items(self):
  41. return self._cache.items()
  42. def __len__(self):
  43. return len(self._cache)