lru_cache.py 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. # Copyright (C) 2011 Google Inc. All rights reserved.
  2. #
  3. # Redistribution and use in source and binary forms, with or without
  4. # modification, are permitted provided that the following conditions are
  5. # met:
  6. #
  7. # * Redistributions of source code must retain the above copyright
  8. # notice, this list of conditions and the following disclaimer.
  9. # * Redistributions in binary form must reproduce the above
  10. # copyright notice, this list of conditions and the following disclaimer
  11. # in the documentation and/or other materials provided with the
  12. # distribution.
  13. # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  14. # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  15. # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  16. # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  17. # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  18. # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  19. # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  20. # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  21. # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  22. # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  23. # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  24. class Node():
  25. def __init__(self, key, value):
  26. self.key = key
  27. self.value = value
  28. self.prev = None
  29. self.next = None
  30. class LRUCache():
  31. """An implementation of Least Recently Used (LRU) Cache."""
  32. def __init__(self, capacity):
  33. """Initializes a lru cache with the given capacity.
  34. Args:
  35. capacity: The capacity of the cache.
  36. """
  37. assert capacity > 0, "capacity (%s) must be greater than zero." % capacity
  38. self._first = None
  39. self._last = None
  40. self._dict = {}
  41. self._capacity = capacity
  42. def __setitem__(self, key, value):
  43. if key in self._dict:
  44. self.__delitem__(key)
  45. if not self._first:
  46. self._one_node(key, value)
  47. return
  48. if len(self._dict) >= self._capacity:
  49. del self._dict[self._last.key]
  50. if self._capacity == 1:
  51. self._one_node(key, value)
  52. return
  53. self._last = self._last.next
  54. self._last.prev = None
  55. node = Node(key, value)
  56. node.prev = self._first
  57. self._first.next = node
  58. self._first = node
  59. self._dict[key] = node
  60. def _one_node(self, key, value):
  61. node = Node(key, value)
  62. self._dict[key] = node
  63. self._first = node
  64. self._last = node
  65. def __getitem__(self, key):
  66. if not self._first:
  67. raise KeyError(str(key))
  68. if self._first.key == key:
  69. return self._first.value
  70. if self._last.key == key:
  71. next_last = self._last.next
  72. next_last.prev = None
  73. next_first = self._last
  74. next_first.prev = self._first
  75. next_first.next = None
  76. self._first.next = next_first
  77. self._first = next_first
  78. self._last = next_last
  79. return self._first.value
  80. node = self._dict[key]
  81. node.next.prev = node.prev
  82. node.prev.next = node.next
  83. node.prev = self._first
  84. node.next = None
  85. self._first.next = node
  86. self._first = node
  87. return self._first.value
  88. def __delitem__(self, key):
  89. node = self._dict[key]
  90. del self._dict[key]
  91. if self._first is self._last:
  92. self._last = None
  93. self._first = None
  94. return
  95. if self._first is node:
  96. self._first = node.prev
  97. self._first.next = None
  98. return
  99. if self._last is node:
  100. self._last = node.next
  101. self._last.prev = None
  102. return
  103. node.next.prev = node.prev
  104. node.prev.next = node.next
  105. def __len__(self):
  106. return len(self._dict)
  107. def __contains__(self, key):
  108. return key in self._dict
  109. def __iter__(self):
  110. return iter(self._dict)
  111. def items(self):
  112. return [(key, node.value) for key, node in self._dict.items()]
  113. def values(self):
  114. return [node.value for node in self._dict.values()]
  115. def keys(self):
  116. return self._dict.keys()