lrucache.py 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. from UserDict import DictMixin
  2. from heapq import heappush, heapify, heapreplace, heappop
  3. import unittest
  4. class LRUCache(dict):
  5. def __init__(self, capacity):
  6. super(LRUCache, self).__init__()
  7. self._lru = []
  8. self._capacity = capacity
  9. def __setitem__(self, key, value):
  10. try:
  11. self._lru.remove(key)
  12. except ValueError:
  13. pass
  14. self._lru.append(key)
  15. while len(self._lru) > self._capacity:
  16. del self[self._lru[0]]
  17. return super(LRUCache, self).__setitem__(key, value)
  18. def __getitem__(self, key):
  19. try:
  20. self._lru.remove(key)
  21. self._lru.append(key)
  22. except ValueError:
  23. pass
  24. return super(LRUCache, self).__getitem__(key)
  25. def __delitem__(self, key):
  26. try:
  27. self._lru.remove(key)
  28. except ValueError:
  29. pass
  30. return super(LRUCache, self).__delitem__(key)
  31. def pop(self, key, default=None):
  32. try:
  33. self._lru.remove(key)
  34. except ValueError:
  35. pass
  36. return super(LRUCache, self).pop(key, default)
  37. def _not_implemented(self, *args, **kw):
  38. raise NotImplementedError
  39. popitem = setdefault = update = _not_implemented
  40. class LRUCacheTestCase(unittest.TestCase):
  41. def test(self):
  42. c = LRUCache(2)
  43. self.assertEqual(len(c), 0)
  44. for i, x in enumerate('abc'):
  45. c[x] = i
  46. self.assertEqual(len(c), 2)
  47. self.assertEqual(set(c), set(['b', 'c']))
  48. self.assertEqual(set(c.iteritems()), set([('b', 1), ('c', 2)]))
  49. self.assertEqual(False, 'a' in c)
  50. self.assertEqual(True, 'b' in c)
  51. self.assertRaises(KeyError, lambda: c['a'])
  52. self.assertEqual(c['b'], 1)
  53. self.assertEqual(c['c'], 2)
  54. c['d'] = 3
  55. self.assertEqual(len(c), 2)
  56. self.assertEqual(c['c'], 2)
  57. self.assertEqual(c['d'], 3)
  58. c['c'] = 22
  59. c['e'] = 4
  60. self.assertEqual(len(c), 2)
  61. self.assertRaises(KeyError, lambda: c['d'])
  62. self.assertEqual(c['c'], 22)
  63. self.assertEqual(c['e'], 4)
  64. del c['c']
  65. self.assertEqual(len(c), 1)
  66. self.assertRaises(KeyError, lambda: c['c'])
  67. self.assertEqual(c['e'], 4)
  68. def test_pop(self):
  69. c = LRUCache(2)
  70. c[1] = 1
  71. c[2] = 2
  72. c.pop(1)
  73. c[3] = 3
  74. def suite():
  75. return unittest.TestLoader().loadTestsFromTestCase(LRUCacheTestCase)
  76. if __name__ == '__main__':
  77. unittest.main()