Skip to content

Commit d31750a

Browse files
Pythonic implementation of LRU Cache (#4630)
* Added a more pythonic implementation of LRU_Cache.[#4628] * Added test cases and doctest * Fixed doc tests * Added more tests in doctests and fixed return types fixes [#4628] * better doctests * added doctests to main() * Added dutch_national_flag.py in sorts. fixing [#4636] * Delete dutch_national_flag.py incorrect commit * Update lru_cache_pythonic.py * Remove pontification --------- Co-authored-by: Christian Clauss <[email protected]>
1 parent 2cfef09 commit d31750a

File tree

1 file changed

+113
-0
lines changed

1 file changed

+113
-0
lines changed

Diff for: other/lru_cache_pythonic.py

+113
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
"""
2+
This implementation of LRU Cache uses the in-built Python dictionary (dict) which from
3+
Python 3.6 onward maintain the insertion order of keys and ensures O(1) operations on
4+
insert, delete and access. https://docs.python.org/3/library/stdtypes.html#typesmapping
5+
"""
6+
from typing import Any, Hashable
7+
8+
9+
class LRUCache(dict):
10+
def __init__(self, capacity: int) -> None:
11+
"""
12+
Initialize an LRU Cache with given capacity.
13+
capacity : int -> the capacity of the LRU Cache
14+
>>> cache = LRUCache(2)
15+
>>> cache
16+
{}
17+
"""
18+
self.remaining: int = capacity
19+
20+
def get(self, key: Hashable) -> Any:
21+
"""
22+
This method returns the value associated with the key.
23+
key : A hashable object that is mapped to a value in the LRU cache.
24+
return -> Any object that has been stored as a value in the LRU cache.
25+
26+
>>> cache = LRUCache(2)
27+
>>> cache.put(1,1)
28+
>>> cache.get(1)
29+
1
30+
>>> cache.get(2)
31+
Traceback (most recent call last):
32+
...
33+
KeyError: '2 not found.'
34+
"""
35+
if key not in self:
36+
raise KeyError(f"{key} not found.")
37+
val = self.pop(key) # Pop the key-value and re-insert to maintain the order
38+
self[key] = val
39+
return val
40+
41+
def put(self, key: Hashable, value: Any) -> None:
42+
"""
43+
This method puts the value associated with the key provided in the LRU cache.
44+
key : A hashable object that is mapped to a value in the LRU cache.
45+
value: Any object that is to be associated with the key in the LRU cache.
46+
>>> cache = LRUCache(2)
47+
>>> cache.put(3,3)
48+
>>> cache
49+
{3: 3}
50+
>>> cache.put(2,2)
51+
>>> cache
52+
{3: 3, 2: 2}
53+
"""
54+
# To pop the last value inside of the LRU cache
55+
if key in self:
56+
self.pop(key)
57+
self[key] = value
58+
return
59+
60+
if self.remaining > 0:
61+
self.remaining -= 1
62+
# To pop the least recently used item from the dictionary
63+
else:
64+
self.pop(next(iter(self)))
65+
self[key] = value
66+
67+
68+
def main() -> None:
69+
"""Example test case with LRU_Cache of size 2
70+
>>> main()
71+
1
72+
Key=2 not found in cache
73+
Key=1 not found in cache
74+
3
75+
4
76+
"""
77+
cache = LRUCache(2) # Creates an LRU cache with size 2
78+
cache.put(1, 1) # cache = {1:1}
79+
cache.put(2, 2) # cache = {1:1, 2:2}
80+
try:
81+
print(cache.get(1)) # Prints 1
82+
except KeyError:
83+
print("Key not found in cache")
84+
cache.put(
85+
3, 3
86+
) # cache = {1:1, 3:3} key=2 is evicted because it wasn't used recently
87+
try:
88+
print(cache.get(2))
89+
except KeyError:
90+
print("Key=2 not found in cache") # Prints key not found
91+
cache.put(
92+
4, 4
93+
) # cache = {4:4, 3:3} key=1 is evicted because it wasn't used recently
94+
try:
95+
print(cache.get(1))
96+
except KeyError:
97+
print("Key=1 not found in cache") # Prints key not found
98+
try:
99+
print(cache.get(3)) # Prints value 3
100+
except KeyError:
101+
print("Key not found in cache")
102+
103+
try:
104+
print(cache.get(4)) # Prints value 4
105+
except KeyError:
106+
print("Key not found in cache")
107+
108+
109+
if __name__ == "__main__":
110+
import doctest
111+
112+
doctest.testmod()
113+
main()

0 commit comments

Comments
 (0)