A least-recently-used cache evicts the retained entry whose last recorded access precedes the others when a new entry exceeds capacity.
Python LRU cache project: make misses, replacement and eviction explicit
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
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
hit: 125
evicted miss: None
retained order: ['R-0043', 'R-0041']
updated: 150Costs 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.
