Implementing LRU Cache Decorator in Python
LRU is the cache replacement algorithm that removes the least recently used data and stores the new data. Suppose we have a cache space of 10 memory frames. And each frame is filled with a file. Now if we want to store the new file, we need to remove the oldest file in the cache and add the new file. This is how LRU works.
LRU cache consists of Queue and Dictionary data structures.
- Queue: to store the most recently used to least recently used files
- Hash table: to store the file and its position in the cache
Refer to the below articles to get more information about the topic:
What is decorator?
A decorator is a function that takes a function as its only parameter and returns a function. This is helpful to “wrap” functionality with the same code over and over again.
Note: For more information, refer to Decorators in Python.
Now, after getting the basic idea about the LRU and Decorators in Python, let’s have a look at the implementation of the LRU cache Decorator in Python.
Python3
from collections import deque
class LRUCache:
def __init__( self , size = 5 ):
self .size = size
self .container = deque()
self . map = dict ()
def reallocate( self ):
if len ( self .container) > 1 :
for key, val in enumerate ( self .container):
self . map [val] = key
def access( self , val):
self .container.remove(val)
self .container.appendleft(val)
self .reallocate()
def evict( self , val):
if val in self . map :
self .container.remove(val)
else :
x = self .container.pop()
del self . map [x]
self .normal_insert(val)
def normal_insert( self , val):
self .container.appendleft(val)
self .reallocate()
def insert( self , val):
if val in self . map .keys():
self .access(val)
else :
if ( len ( self . map .keys()) = = self .size):
self .evict(val)
else :
self .normal_insert(val)
def print ( self ):
lru_elements = [x for x in self .container]
print (lru_elements)
def LRUDecorator(size):
lru = LRUCache(size)
def decorator(function):
def functionality(num):
lru.insert(num)
lru. print ()
print (num, function(num))
return functionality
return decorator
@LRUDecorator (size = 4 )
def ex_func_01(n):
print (f 'Computing...{n}' )
time.sleep( 1 )
return n
print (f '\nFunction: ex_func_01' )
print (ex_func_01( 1 ))
print (ex_func_01( 2 ))
print (ex_func_01( 3 ))
print (ex_func_01( 4 ))
print (ex_func_01( 1 ))
print (ex_func_01( 2 ))
print (ex_func_01( 5 ))
print (ex_func_01( 1 ))
print (ex_func_01( 2 ))
print (ex_func_01( 3 ))
print (ex_func_01( 4 ))
print (ex_func_01( 5 ))
|
Output:
Function: ex_func_01
[1]
Computing...1
1 1
None
[2, 1]
Computing...2
2 2
None
[3, 2, 1]
Computing...3
3 3
None
[4, 3, 2, 1]
Computing...4
4 4
None
[1, 4, 3, 2]
Computing...1
1 1
None
[2, 1, 4, 3]
Computing...2
2 2
None
[5, 2, 1, 4]
Computing...5
5 5
None
[1, 5, 2, 4]
Computing...1
1 1
None
[2, 1, 5, 4]
Computing...2
2 2
None
[3, 2, 1, 5]
Computing...3
3 3
None
[4, 3, 2, 1]
Computing...4
4 4
None
[5, 4, 3, 2]
Computing...5
5 5
None
Last Updated :
19 Aug, 2021
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment...