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 <cclauss@me.com>
This commit is contained in:
Yatharth Mathur 2023-07-30 02:27:45 -07:00 committed by GitHub
parent 2cfef0913a
commit d31750adec
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

113
other/lru_cache_pythonic.py Normal file
View File

@ -0,0 +1,113 @@
"""
This implementation of LRU Cache uses the in-built Python dictionary (dict) which from
Python 3.6 onward maintain the insertion order of keys and ensures O(1) operations on
insert, delete and access. https://docs.python.org/3/library/stdtypes.html#typesmapping
"""
from typing import Any, Hashable
class LRUCache(dict):
def __init__(self, capacity: int) -> None:
"""
Initialize an LRU Cache with given capacity.
capacity : int -> the capacity of the LRU Cache
>>> cache = LRUCache(2)
>>> cache
{}
"""
self.remaining: int = capacity
def get(self, key: Hashable) -> Any:
"""
This method returns the value associated with the key.
key : A hashable object that is mapped to a value in the LRU cache.
return -> Any object that has been stored as a value in the LRU cache.
>>> cache = LRUCache(2)
>>> cache.put(1,1)
>>> cache.get(1)
1
>>> cache.get(2)
Traceback (most recent call last):
...
KeyError: '2 not found.'
"""
if key not in self:
raise KeyError(f"{key} not found.")
val = self.pop(key) # Pop the key-value and re-insert to maintain the order
self[key] = val
return val
def put(self, key: Hashable, value: Any) -> None:
"""
This method puts the value associated with the key provided in the LRU cache.
key : A hashable object that is mapped to a value in the LRU cache.
value: Any object that is to be associated with the key in the LRU cache.
>>> cache = LRUCache(2)
>>> cache.put(3,3)
>>> cache
{3: 3}
>>> cache.put(2,2)
>>> cache
{3: 3, 2: 2}
"""
# To pop the last value inside of the LRU cache
if key in self:
self.pop(key)
self[key] = value
return
if self.remaining > 0:
self.remaining -= 1
# To pop the least recently used item from the dictionary
else:
self.pop(next(iter(self)))
self[key] = value
def main() -> None:
"""Example test case with LRU_Cache of size 2
>>> main()
1
Key=2 not found in cache
Key=1 not found in cache
3
4
"""
cache = LRUCache(2) # Creates an LRU cache with size 2
cache.put(1, 1) # cache = {1:1}
cache.put(2, 2) # cache = {1:1, 2:2}
try:
print(cache.get(1)) # Prints 1
except KeyError:
print("Key not found in cache")
cache.put(
3, 3
) # cache = {1:1, 3:3} key=2 is evicted because it wasn't used recently
try:
print(cache.get(2))
except KeyError:
print("Key=2 not found in cache") # Prints key not found
cache.put(
4, 4
) # cache = {4:4, 3:3} key=1 is evicted because it wasn't used recently
try:
print(cache.get(1))
except KeyError:
print("Key=1 not found in cache") # Prints key not found
try:
print(cache.get(3)) # Prints value 3
except KeyError:
print("Key not found in cache")
try:
print(cache.get(4)) # Prints value 4
except KeyError:
print("Key not found in cache")
if __name__ == "__main__":
import doctest
doctest.testmod()
main()