Free tools Windows power users keep installed
One-click scans. No signup required.
Memoization lets a function skip work it has already done. The first time it receives a given input, it computes the result and stores it. When it receives that same input again, it returns the stored value without running the computation again. This saves time only when inputs actually repeat and the stored answer is still valid. In exchange, it uses memory, adds lookup overhead, and can return wrong results when the function depends on state that has changed.
What memoization means
MDN Web Docs defines the term in its glossary: “Memoization is an optimization technique that stores the result of a function call and returns the stored result when the function is called again with the same inputs.” (MDN Web Docs, “Memoization – Glossary.”) The key idea is that the inputs act as the lookup key. Two calls with identical inputs are treated as the same question, so the second one can reuse the first answer.
Memoization is a deliberate, narrow optimization. It does not make a program faster in general. It removes repeated computation for one function, and only where that function is pure enough for old answers to remain correct.
How memoization works
- The function is wrapped so that every call passes through a lookup table, usually a dictionary held in memory.
- The arguments are turned into a key. In Python, this key must be hashable.
- On a miss (the key is not in the table), the real function runs, its result is stored under that key, and the result is returned.
- On a hit (the key is already stored), the stored result is returned and the function body does not execute.
- The table grows with each new key until it is capped by a size limit or cleared explicitly.
Every hit saves one full execution of the function body. Every miss costs a little extra, because the lookup and the store both have to happen. That trade-off is why memoization helps in some programs and does nothing for others.
#1 Best Overall
When memoization is worth using
Good candidates
- Functions whose output depends only on their arguments, so the same input always yields the same output.
- Functions with no side effects, such as writing files, sending messages, or changing global state each time they run.
- Expensive computations that are called repeatedly with the same inputs, such as recursive subproblems that overlap.
- Workloads where the set of distinct inputs is small compared with the number of calls.
Poor candidates
- Functions with mostly unique inputs. Every call is a miss, so you pay the storage cost and gain nothing.
- Cheap computations. The lookup can cost as much as the work it saves.
- Functions whose result depends on the current time, random numbers, or other hidden inputs, unless those inputs are part of the key.
- Functions that read a database, file, or configuration value that can change while the program runs.
When results depend on hidden inputs, you have two options: add those inputs to the key, or define an invalidation rule that clears entries when the underlying data changes. If neither is possible, do not memoize the function.
Memoization versus caching
Caching is the broad category: keeping a copy of something expensive so you do not have to produce it again. Memoization is one specific kind of caching, applied to the results of function calls and keyed by their arguments. Browser and HTTP caches work at a different layer, storing responses to requests. The table below compares the three.
| Aspect | Function memoization | Browser Cache API | HTTP caching |
|---|---|---|---|
| What is stored | Return value of a function call | Request and response pairs created by application code | HTTP responses, reused between a client and a server or intermediary |
| How entries are keyed | The function’s arguments | The request that the application stores | The request URL and the headers that determine whether a response matches |
| Freshness and expiry | None automatic. Entries stay until cleared, evicted by a size limit, or the process ends | Entries do not update or expire automatically. Application code must update and purge them (MDN Web Docs, “Cache – Web APIs”) | Governed by HTTP freshness and validation rules (MDN Web Docs, “HTTP caching”) |
| Who manages invalidation | Your code | Your code | Largely the protocol, through response headers |
| Typical scope | One running process | One browser origin | Client, proxy, or server side, depending on deployment |
The practical difference is who is responsible for correctness. HTTP caching follows rules defined by the protocol. The Cache API does not follow HTTP caching headers automatically, so the application decides when stored responses are stale. Memoization is entirely in your code, so the cache is correct only as long as you have modeled the function’s dependencies correctly.
Rank #2
- 【Package Included】You will get 2pcs phone message book, 200 sets/book,400sets in total. Each receipt book is divided into 2 parts,white,yellow.
- 【Material】Our message pads are made of paper, not easy to tear, large quantity can meet long time uses.
- 【Easy to Use】The durable tear-off design allows you to easily tear off the white message, while the yellow stub copy remains securely attached to the spiral.
- 【Spiral-Bound 】The neat spiral binding design keeps your duplicate stubs securely organized in chronological order, providing you with a complete and permanent record of all missed calls and messages.
- 【Pre-Printed Prompts】Key details and prompts—such as the caller's name, the purpose of the call, and preferred callback methods—are pre-printed on each page, ensuring that you never overlook or miss recording any vital information.
Memoization and dynamic programming
Dynamic programming is a broader approach to problems whose subproblems overlap. It has two common forms. The top-down form starts from the original problem, recurses into subproblems, and stores each subproblem’s result as it is computed. That top-down form is usually implemented with memoization. The bottom-up form fills a table from the smallest subproblems upward and does not use recursion.
Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Memoization is therefore one way to implement part of dynamic programming. It is not the whole method, and not every cache is a memoization of a dynamic programming problem.
How to memoize a function in Python
Python’s standard library provides memoization in the functools module. The Python Software Foundation’s documentation for functools (Python 3.14 edition) describes two main options.
Unbounded cache with @cache
functools.cache stores every distinct call with no size limit. The Python documentation states it is equivalent to lru_cache(maxsize=None). It is the simplest choice, but memory grows with every new key. Use it only when the number of distinct inputs is bounded or when growth is acceptable.
Bounded cache with @lru_cache(maxsize=...)
functools.lru_cache keeps up to maxsize recent results and discards the least recently used entry when the limit is reached. Its documented default is maxsize=128. Set the limit explicitly to match the memory you are willing to spend.
Outdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchPC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11from functools import lru_cache
@lru_cache(maxsize=256)
def expensive_lookup(key):
return compute_result(key)
This is appropriate only if compute_result(key) stays valid for the same key for as long as the entry remains in the cache. If the underlying data changes, call expensive_lookup.cache_clear() after the change, or add a version value to the arguments so that a new version produces new keys.
Rank #4
Worked example: recursive Fibonacci
Naive recursive Fibonacci recomputes the same smaller values many times. Adding a cache means each value is computed once and then reused:
from functools import lru_cache
@lru_cache(maxsize=None)
def fib(n):
if n < 2:
return n
return fib(n - 1) + fib(n - 2)
fib(20)
print(fib.cache_info())
The Python documentation uses this same pattern and reports CacheInfo(hits=28, misses=16, maxsize=None, currsize=16) for the sequence of calls it illustrates. Those numbers describe that example only. They are not a general measure of speed, and your results will depend on the function and the call pattern. cache_info() returns the hit and miss counts, which is the simplest way to check whether a cache is being reused at all.
Keys and hashable arguments
The cache uses dictionary-based lookup, so every argument must be hashable. Passing a list or dictionary raises TypeError. Convert such arguments to a tuple or a frozenset before the call, or redesign the function so it accepts hashable values.
Recommended Free Tools
Best Value
Keyword arguments also affect identity. Python’s documentation notes that the same arguments passed in a different keyword order may be stored as separate entries. Pick one calling convention for a memoized function and use it consistently.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Failure modes and how to handle them
- Stale results. A value computed from data that later changed will keep being returned. Clear the cache with
cache_clear()when the data changes, or include a version or timestamp in the arguments. - Unbounded memory growth.
@cachenever evicts entries. Switch to@lru_cache(maxsize=...)if the set of inputs can grow without limit. - Repeated execution under concurrency. With concurrent use, the underlying function can be called more than once before its first result is stored. This is harmless for a pure function that is cheap to repeat. If the function is expensive or has side effects, serialize calls with a lock or redesign the function.
- Shared mutable results. The cache returns the same object each time. If a caller modifies a returned list or dictionary, later callers receive the modified object. Return immutable values such as tuples, or copy the result before changing it.
- Memoizing methods. Using a cache decorator on an instance method includes
selfin the key and keeps instances alive for as long as their entries remain in the cache. Prefer a cache on a module-level function, or store results on the instance itself.
The common thread is that the cache is only as correct as your model of what the function depends on. When the function’s inputs are complete and its output is stable, memoization removes repeated work cleanly. When they are not, the cache quietly returns answers that were correct at some earlier point.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




