Python

Python Functools Lru_Cache

Python’s functools module deals with higher functions or those that operate on (and take as parameters) or return the other callable objects like functions. The functools module offers a variety of functions including wraps(func), lru_cache(func), cmp to key(func), and cached property(func). It’s important to note that these methods accept parameters that are functions. Memoization is a performance-enhancing method used by many languages, and Python is no exception. Memoization involves caching the outcomes of a method call so that the subsequent calls with identical inputs don’t require recalculating the results from scratch.

Lru_cache, a standard library tool provided by Python, can be used to accomplish this. A decorator called lru_cache() uses the memoization approach to shorten the length of time that a function is executed for the same inputs.

To examine the efficacy of the cache and optimize the maxsize argument, the wrapped method offers the cache_info() method that creates a labeled tuple comprising hits, failures, maxsize, and currsize. Because lru_cache defaults to caching every call to the method it encapsulates, the cache can continue to expand indefinitely while a program is running.

You probably don’t need to be concerned about the cache getting too big if the range of arguments that your function accepts is limited (for example, the only numbers 1 through 100). To prevent using up all the memory, you might want to limit the cache in some circumstances to the maximum X possibilities.
The “lru” in lru_cache originates from here. LRU or least frequently used is a term used to describe how the objects in the cache are instantly removed. All data are removed and saved for the most recent X cached items.

Syntax of the lru_cache in Python

One such functools module function that aids in decreasing the function execution time by applying memoization technique is the lru_cache(). The following is the syntax of the lru_cache provided by Python:

@lru_cache(maxsize=128, typed=False)

The decorator @lru_cache takes two parameters:

Max_size: The cache’s maximum storage capacity is indicated by this option after which the older items are removed. When it is set to zero, no data will ever be removed from the cache, which causes it to grow eternally. If a lot of data is cached, this will result in issues.

Types: This argument is Boolean. Having different entries in the cache for various sorts of function parameters is indicated when the value is set to True.

Example 1: Program to Print the Fibonacci Series

As the name implies, the cache maintains the most current inputs/results pair by eliminating the least recent/oldest records first. With the aid of the lru cache, we’ll print the Fibonacci sequence. For instance, the simple Fibonacci series is 1, 1, 2, 3, 5, 8, etc. since 1+1 = 2, 1+2 = 3, and so forth. Let’s compare the times the function takes while using the lru_cache and when it isn’t used by using time.

from functools import lru_cache
import time
def fib_without_cache(n):
    if n < 4:
        return n
    return fib_without_cache(n-1) + fib_without_cache(n-4)
   
begin = time.time()
fib_without_cache(60)
end = time.time()
print("Time execution without lru_cache is", end-begin)
@lru_cache(maxsize = 128)
def fib_with_cache(n):
    if n < 4:
        return n
    return fib_with_cache(n-1) + fib_with_cache(n-2)
   
begin = time.time()
fib_with_cache(60)
end = time.time()

print("Time execution with lru_cache is", end-begin)

Here, from the Python functools module, we imported the lru_cache. The time is also imported in this script for the time execution. Then, we have a function definition that has given the name “fib_without_cache”. The function was created to compute the Fibonacci series without the lru_cache. Inside the function with the if condition, we computed the Fibonacci series by applying its formula.

After that, we created an object “begin” where the time function is invoked. The time in seconds is passed to the “fib_without_cache” function. With the end object, we ended the time execution. The Fibonacci series is printed without the lru_cache by the print command. The Fibonacci series was implemented without the lru_cache function, as we demonstrated.

Now, we deploy the lru_cache function. We set the input max_size value to the lru_cache function. Using the lru_cache decorator, we then wrapped the “fib_with_cache” function. The Fibonacci series can be determined very quickly by doing this. The Fibonacci series is evaluated by applying its formula. The time execution starts with the beginning object and ends with the end object. Lastly, we printed the result that is formed with the lru_cache decorator.

You can see the output of the Fibonacci series with and without the lru cache decorator as follows:

Example 2: Program to Count the Vowel from the String

We count the number of vowels that the provided string has by utilizing the lru_cache decorator.

from functools import lru_cache
@lru_cache(maxsize = 50)
def count_vowels(string):
    string = string.casefold()
    return sum(string.count(vowel) for vowel in 'aeiou')
   
print(count_vowels("Hello geeks"))

First, we included the lru_cache in our script and then used the lru_cache decorator. Inside the lru_cache decorator, we passed the maxsize as an argument and set its value to 50. Then, we created a function with the name “count_vowels” that takes the variable “string” as an input. We set the casefold method in the string variable. The casefold method here converts the characters to the lower case given in the string.

Then, we have the return command which gives the sum of the vowels found in the string. To the print statement, we specified the “Hello geeks” string.

The following is an integer value obtained which is the sum of the vowel found in the string:

Conclusion

We covered the lru_cache in Python with its syntax and examples. The output and parameters are saved when a function enclosed in the lru_cache is called. The function is then called again, and if the same input is found, the output from the previous call is returned without performing any calculations.

About the author

Kalsoom Bibi

Hello, I am a freelance writer and usually write for Linux and other technology related content