Skip to content
AITroveRead. Build. Understand.
Make this comfortable

Python LRU cache project: make misses, replacement and eviction explicit

Last updated: 30 Sept 20264 min read
tutorial
IntermediateBy AITrove Editorial

A least-recently-used cache evicts the retained entry whose last recorded access precedes the others when a new entry exceeds capacity.

Download Python source kit

Operation contract

The receipt cache accepts one to sixteen entries with fixed ASCII IDs and exact bounded integer values. Get returns None for a miss and moves a hit to the newest end. Put updates an existing key without increasing retained count, or inserts and evicts the oldest key. All input validation precedes mutation, so a rejected amount cannot alter access order.

Failure and ownership boundary

None cannot be a stored value in this contract, so it is an unambiguous miss. The cache is process-local, has no expiry and is not synchronized across threads. Mutating the exposed internal dictionary bypasses its invariant. Python OrderedDict: explicit reordering differs from insertion order, Python lru_cache: bound retention and include the revision in the key and Python locks: protect the complete inventory transition have different policies.

Working program

python
from collections import OrderedDict
import re

class ReceiptCache:
    def __init__(self, capacity):
        if type(capacity) is not int or not 1 <= capacity <= 16:
            raise ValueError("capacity rejected")
        self.capacity = capacity; self.entries = OrderedDict()
    def _key(self, key):
        if not isinstance(key, str) or re.fullmatch(r"R-[0-9]{4}", key) is None:
            raise ValueError("cache key rejected")
    def get(self, key):
        self._key(key)
        if key not in self.entries: return None
        self.entries.move_to_end(key)
        return self.entries[key]
    def put(self, key, amount):
        self._key(key)
        if type(amount) is not int or not 0 <= amount <= 1000000:
            raise ValueError("cache amount rejected")
        self.entries[key] = amount; self.entries.move_to_end(key)
        if len(self.entries) > self.capacity: self.entries.popitem(last=False)

cache = ReceiptCache(2)
cache.put("R-0041", 125); cache.put("R-0042", 250)
print("hit:", cache.get("R-0041"))
cache.put("R-0043", 75)
print("evicted miss:", cache.get("R-0042"))
cache.put("R-0041", 150)
print("retained order:", list(cache.entries))
print("updated:", cache.get("R-0041"))

Output

Output
hit: 125
evicted miss: None
retained order: ['R-0043', 'R-0041']
updated: 150

Costs and limits

Expected lookup/update/endpoint eviction work is constant under suitable hashes. Retained state is O(capacity) and accepted values are immutable integers. This implementation makes no stale-data detection or cross-process consistency guarantee.

Common Mistakes

  • Define a miss representation that cannot be confused with a stored value.
  • Validate rejected writes before changing order or contents.

Connected lessons

Python OrderedDict: explicit reordering differs from insertion order, Python lru_cache: bound retention and include the revision in the key, Python locks: protect the complete inventory transition.

Follow the service contract

Python TTL cache: expire at a defined boundary and use an injected clock.

python
lru-project
Storage details