_lru_cache.py 1.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
  1. from typing import TYPE_CHECKING
  2. if TYPE_CHECKING:
  3. from typing import Any
  4. _SENTINEL = object()
  5. class LRUCache:
  6. def __init__(self, max_size):
  7. # type: (int) -> None
  8. if max_size <= 0:
  9. raise AssertionError(f"invalid max_size: {max_size}")
  10. self.max_size = max_size
  11. self._data = {} # type: dict[Any, Any]
  12. self.hits = self.misses = 0
  13. self.full = False
  14. def set(self, key, value):
  15. # type: (Any, Any) -> None
  16. current = self._data.pop(key, _SENTINEL)
  17. if current is not _SENTINEL:
  18. self._data[key] = value
  19. elif self.full:
  20. self._data.pop(next(iter(self._data)))
  21. self._data[key] = value
  22. else:
  23. self._data[key] = value
  24. self.full = len(self._data) >= self.max_size
  25. def get(self, key, default=None):
  26. # type: (Any, Any) -> Any
  27. try:
  28. ret = self._data.pop(key)
  29. except KeyError:
  30. self.misses += 1
  31. ret = default
  32. else:
  33. self.hits += 1
  34. self._data[key] = ret
  35. return ret
  36. def get_all(self):
  37. # type: () -> list[tuple[Any, Any]]
  38. return list(self._data.items())