The functools module in Python provides several utilities to help with function decorators, and one of the most useful features is caching, which helps optimize the performance of functions by storing previously computed results. The functools.cache functions (lru_cache, cache_property, cache_on_self) are specifically designed for this purpose.
Here are 10 Python code snippets that demonstrate how to use caching with functools to improve the performance of various functions:
1. Basic Caching with lru_cache
from functools import lru_cache@lru_cache(maxsize=None)# No limit on the cache sizedefslow_function(x):print("Computing...")return x * x# Usageprint(slow_function(5))# Computes and caches the resultprint(slow_function(5))# Retrieves the cached result
2. Caching with maxsize Parameter
from functools import lru_cache@lru_cache(maxsize=3)# Cache the last 3 callsdefslow_function(x):print("Computing...")return x * x# Usageprint(slow_function(1))# Computes and caches the resultprint(slow_function(2))# Computes and caches the resultprint(slow_function(3))# Computes and caches the resultprint(slow_function(4))# Computes and caches the result, evicts oldest (1)print(slow_function(1))# Computes again, as 1 was evicted
3. Clearing Cache Manually
4. Using cache_property for Cached Properties
5. Using Cache with Mutable Arguments
6. Caching with Functions that Have Default Arguments
7. Using cache_on_self for Method Caching
8. Performance Boost with Cache for Recursion
9. LRU Cache with Custom Key Function
10. Handling Cache Misses with Default Values
In these snippets:
lru_cache(maxsize) is used for caching results of functions with positional and keyword arguments.
cached_property caches the result of a method call as a property, avoiding recomputation.
The cache size can be controlled with the maxsize parameter, and the cache can be cleared manually using cache_clear().
Caching significantly boosts performance when dealing with expensive or recursive computations by avoiding redundant calculations.
from functools import lru_cache
@lru_cache(maxsize=3)
def slow_function(x):
print("Computing...")
return x * x
# Usage
print(slow_function(2)) # Computes and caches the result
slow_function.cache_clear() # Clears the cache manually
print(slow_function(2)) # Computes again after cache is cleared
from functools import cached_property
class MyClass:
@cached_property
def expensive_computation(self):
print("Computing expensive result...")
return 42
# Usage
obj = MyClass()
print(obj.expensive_computation) # Computes and caches the result
print(obj.expensive_computation) # Retrieves the cached result
from functools import lru_cache
@lru_cache(maxsize=2)
def slow_function(a, b):
print("Computing...")
return a + b
# Usage
print(slow_function(1, 2)) # Computes and caches the result
print(slow_function(1, 2)) # Retrieves the cached result
print(slow_function(2, 3)) # Computes and caches the result
from functools import lru_cache
@lru_cache(maxsize=None)
def slow_function(a, b=2):
print("Computing...")
return a * b
# Usage
print(slow_function(3)) # Computes with default b=2
print(slow_function(3, 4)) # Computes with b=4
print(slow_function(3)) # Retrieves the cached result for a=3, b=2
from functools import cache_on_self
class MyClass:
@cache_on_self
def method(self, x):
print("Computing...")
return x * 2
# Usage
obj = MyClass()
print(obj.method(5)) # Computes and caches the result
print(obj.method(5)) # Retrieves the cached result
from functools import lru_cache
@lru_cache(maxsize=None)
def fibonacci(n):
if n <= 1:
return n
return fibonacci(n-1) + fibonacci(n-2)
# Usage
print(fibonacci(30)) # Fast computation with caching
from functools import lru_cache
def custom_key(a, b):
return a + b
@lru_cache(maxsize=None, key=custom_key)
def slow_function(a, b):
print("Computing...")
return a * b
# Usage
print(slow_function(2, 3)) # Computes and caches
from functools import lru_cache
@lru_cache(maxsize=None)
def slow_function(a):
print("Computing...")
return a * 2
# Usage
print(slow_function(10)) # Computes and caches
print(slow_function(20)) # Computes and caches
print(slow_function(10)) # Retrieves the cached result for 10