_lru_cache.py 1.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243
  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: int) -> None:
  7. if max_size <= 0:
  8. raise AssertionError(f"invalid max_size: {max_size}")
  9. self.max_size = max_size
  10. self._data: "dict[Any, Any]" = {}
  11. self.hits = self.misses = 0
  12. self.full = False
  13. def set(self, key: "Any", value: "Any") -> None:
  14. current = self._data.pop(key, _SENTINEL)
  15. if current is not _SENTINEL:
  16. self._data[key] = value
  17. elif self.full:
  18. self._data.pop(next(iter(self._data)))
  19. self._data[key] = value
  20. else:
  21. self._data[key] = value
  22. self.full = len(self._data) >= self.max_size
  23. def get(self, key: "Any", default: "Any" = None) -> "Any":
  24. try:
  25. ret = self._data.pop(key)
  26. except KeyError:
  27. self.misses += 1
  28. ret = default
  29. else:
  30. self.hits += 1
  31. self._data[key] = ret
  32. return ret
  33. def get_all(self) -> "list[tuple[Any, Any]]":
  34. return list(self._data.items())