141. Decorators for Caching Results

Using decorators like functools.lru_cache in Python allows you to cache the results of expensive function calls, thus improving the performance of the application by avoiding repeated computation for the same inputs. Here are 10 Python snippets for using caching decorators, particularly lru_cache and custom decorators for caching results.

1. Basic Caching with lru_cache

Using lru_cache to cache results of a function based on its arguments.

Copy

from functools import lru_cache

@lru_cache(maxsize=None)  # Unlimited cache size
def expensive_computation(n):
    print(f"Computing {n}...")
    return n * n

# First call, performs the computation
print(expensive_computation(4))  
# Second call, retrieves from cache
print(expensive_computation(4))  

Output:

Copy

Computing 4...
16
16

Explanation:

  • The first time expensive_computation(4) is called, it performs the calculation and caches the result.

  • The second time the same value is requested, the cached result is returned, avoiding the computation.

2. Caching with lru_cache with a Limited Cache Size

Using lru_cache with a specified maximum cache size.

Copy

Output:

Copy

Explanation:

  • The cache holds a maximum of 3 results. Once more results are added, the least recently used results are evicted.

3. Caching with Custom Decorators

You can implement a custom caching decorator if you want more control over the cache.

Copy

Output:

Copy

Explanation:

  • The cache_decorator manually caches results based on the arguments passed to the function.

4. Caching Function Results with lru_cache for Fibonacci Numbers

A classic example of using lru_cache for improving performance when calculating Fibonacci numbers.

Copy

Output:

Copy

Explanation:

  • The recursive fibonacci function benefits from lru_cache by caching previously computed Fibonacci numbers, significantly improving performance.

5. Caching with Function Arguments as Keys

You can use lru_cache with arguments that are hashable and work efficiently for caching.

Copy

Output:

Copy

Explanation:

  • The concat_strings function concatenates two strings and caches the result based on the argument values.

6. Memoization for Repeated Function Calls

Use caching to optimize functions that are called repeatedly with the same arguments.

Copy

Output:

Copy

Explanation:

  • The factorial function benefits from caching, as repeated calls with the same argument don't require recomputation.

7. Clearing the Cache Manually

You can clear the cache manually when needed.

Copy

Output:

Copy

Explanation:

  • The cache_clear() method clears the cache manually, causing the next call to recompute the result.

8. Conditional Caching

You can apply caching only under certain conditions, like the length of the argument list.

Copy

Output:

Copy

Explanation:

  • The function caches results based on the conditions set inside the decorator.

9. Caching Results in Web Applications

In web applications, caching helps with storing frequently requested resources to improve speed.

Copy

Output:

Copy

Explanation:

  • In web apps, functions like database queries can be cached to avoid querying the database multiple times for the same data.

10. Custom Cache Timeout

Implementing a custom cache timeout mechanism to invalidate cached values after a certain period.

Copy

Output:

Copy

Explanation:

  • The custom cache_with_timeout decorator stores the result for a specified timeout. After the timeout expires, the cache is invalidated, and the function is recomputed.


Conclusion:

Caching with decorators like lru_cache and custom caching mechanisms can greatly improve performance by preventing redundant calculations. These examples demonstrate different ways to apply caching to functions based on various use cases, from simple memoization to more complex custom timeout-based caches.

Last updated