lrucache.py 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152
  1. class LRUCache(dict):
  2. def __init__(self, capacity, dispose):
  3. super(LRUCache, self).__init__()
  4. self._lru = []
  5. self._capacity = capacity
  6. self._dispose = dispose
  7. def __setitem__(self, key, value):
  8. assert key not in self, (
  9. "Unexpected attempt to replace a cached item."
  10. " If this is intended, please delete or pop the old item first."
  11. " The dispose function will be called on delete (but not pop).")
  12. self._lru.append(key)
  13. while len(self._lru) > self._capacity:
  14. del self[self._lru[0]]
  15. return super(LRUCache, self).__setitem__(key, value)
  16. def __getitem__(self, key):
  17. try:
  18. self._lru.remove(key)
  19. self._lru.append(key)
  20. except ValueError:
  21. pass
  22. return super(LRUCache, self).__getitem__(key)
  23. def __delitem__(self, key):
  24. try:
  25. self._lru.remove(key)
  26. except ValueError:
  27. pass
  28. error = KeyError(key)
  29. removed = super(LRUCache, self).pop(key, error)
  30. if removed == error:
  31. raise error
  32. self._dispose(removed)
  33. def pop(self, key, default=None):
  34. try:
  35. self._lru.remove(key)
  36. except ValueError:
  37. pass
  38. return super(LRUCache, self).pop(key, default)
  39. def clear(self):
  40. for value in self.values():
  41. self._dispose(value)
  42. super(LRUCache, self).clear()
  43. def _not_implemented(self, *args, **kw):
  44. raise NotImplementedError
  45. popitem = setdefault = update = _not_implemented