What is memoization and how can I use it in Python?
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.
Introduction
Memoization is an optimization technique used primarily to speed up computer programs by storing the results of expensive function calls and returning the cached result when the same inputs occur again. It is particularly useful in scenarios involving recursive functions and expensive computation tasks. In Python, memoization can be implemented through different methods, ranging from simple dictionaries to more sophisticated decorators like `functools.lru_cache`.
How Memoization Works
Memoization involves caching the results of function calls and using these cached results in subsequent calls with the same arguments instead of recomputing them. This technique is particularly efficient for functions with overlapping subproblems like those found in recursive algorithms.
Key Concepts
- Cache: A storage layer where the results of expensive function calls are stored.
- Lookup: The process of checking if a cached result is available for a given set of parameters.
- Storage/Insertion: The process of storing a function's result when it is computed for a set of parameters for the first time.
Example of Memoization
Let's illustrate memoization with an example of computing Fibonacci numbers, which is a classic problem where memoization can be hugely beneficial.
- We use a dictionary `cache` to store the Fibonacci numbers that have already been calculated.
- If `n` is found in `cache`, the function returns the cached value.
- If not, the function is called recursively to compute the Fibonacci number, and the result is stored in `cache`.
- `maxsize=None` indicates that the cache can grow indefinitely.
- This cached method is far cleaner and requires less manual handling of caching logic than the manual method.
- Ease of Use: Tools like `lru_cache` make it straightforward to implement memoization without manual intervention.
- Performance: Significant speedup in recursive algorithms with overlapping subproblems.
- Cleaner Code: Separation of logic for computation and optimization aspect.
- Memory Use: Cache might consume significant memory for large computations or when used without a bound.
- Not for All Functions: Functions with side effects or those depending on external states are not suitable for memoization.
Related reading
- What is message-oriented middleware?
- What is middleware in distributed systems?
- What is pip's --no-cache-dir good for?
- What is pip's --no-cache-dir good for?
- what is Newton-Raphson Square Method's time complexity?
- What is NSZombie?
- What is monkey patching?
- What is PEP8's E128 continuation line under-indented for visual indent?

System Design Fundamentals
Build a strong foundation in designing scalable, reliable distributed systems.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.