# What Is Memoization in Python

Last updated on
08th Jun, 2022
Published
23rd Apr, 2021
Views
9,358  The term memoization gets its name from the Latin word memorandum meaning — ‘to be remembered’. Donald Michie, a British researcher in AI, introduced the term in the year 1968. It may look like a misspelling of the word memorization, but it comprises recording a value to look upon the function later. Above all, it is often a crucial technique in solving problems using Dynamic Programming.

Check out the article on Self in Python here! ## Definition of Memoization

Memoization is an efficient software optimization technique used to speed up programs. It allows you to optimize a python function by catching its output based on the supplied input parameters. Memoization ensures that a method runs for the same input only once. Moreover, it keeps the output records for the given set of inputs in a hash map. That means, when you memorize a function, it will only compute the output once for every set of parameters called-with.

### Fibonacci sequence

A Fibonacci sequence is a series where each term is the sum of the preceding two terms. It plays a vital role in testing the memorization decorator recursively. We begin by defining the python function that calculates the nth Fibonacci number.

Program to find Fibonacci Series using recursive functions.

```def fibonacci(n):
if (n < 2):
return 1
return (fibonacci(n - 1) + fibonacci(n - 2))
print(fibonacci(8)) ```

Output:

`34 `

Note: The Fibonacci series we got using a recursive function takes strenuous efforts plus consumes a lot of time. Calculating the nth Fibonacci number this way has an overall runtime of 0(2^n) – the code takes exponential time to execute. It seems expensive, right?

### Fibonacci with Memoization

To speed up the program, we will take advantage of memoize() function by defining it. Let us understand with the help of an example.

```def memoize(k):
fast = {}
def partner(l):
if l not in fast:
fast[l] = k(l)
return fast[l]
return partner
def fibonacci(n):
if (n<2):
return 1
return (fibonacci(n-1) + fibonacci(n-2))
fibonacci = memoize(fibonacci)
print(fibonacci(25))  ```

Output:

`121393 `

The memoize() takes a function as an argument and uses a dictionary to store results. In the code, you will find the partner function captures the variable “fast” and the function “k” – which gets returned as a reference by memoizing(). So, the call memoize(fibonacci) returns a reference to the partner() doing the same work as fibonacci() would do on its own, saving time.

### Memoization with Function Decorators

Python comes up with additional capabilities, helping programmers to add functionalities to a pre-existing code. It allows the implementation of the memoization algorithm seamlessly with no hassle. The above code can be written in a more sophisticated manner using decorator.

### Let’s Write a Memoization Decorator from Scratch

Let’s rewrite the above code by replacing fibonacci = memoize(Fibonacci) with a decorator. We have decorated our Fibonacci function using @memoize.

```def memoize(f):
fast = {}
def partner(l):
if l not in fast:
fast[l] = f(l)
return fast[l]
return partner
@memoize
def fibonacci(n):
if (n < 2):
return 1
return (fibonacci(n - 1) + fibonacci(n - 2))
print(fibonacci(25))```

Output:

`121393 `

### Using a Callable Class for Memoization

Python also allows encapsulating the results using a callable class. Let’s have a look with an example:

```class Memoize:
def __init__(self, gx):
self.gx = gx
self.fast = {}
def __call__(self, *args):
if args not in self.fast:
self.fast[args] = self.gx(*args)
return self.fast[args]
@Memoize
def fibonacci(n):
if (n < 2):
return 1
return (fibonacci(n - 1) + fibonacci(n - 2))
print(fibonacci(25)) ```

Output:

`121393 `

## Why and When Should You Use Memoization in Your Python Programs?

The idea behind memoization –

1. Implementation simplicity
2. Algorithm maturity
3. Very high performance To solve a problem when the sub-problems have to be solved repeatedly – we use memoization. Try fibonacci(25), and you will find the execution time at snail speed. Perhaps you have to wait about ten seconds to get the final output. Usually, memoization is an operation you can apply to any function that computes something (expensive) and returns a value. The total time, therefore, is O(n^3). Memoization thus turns an O(n^2)-time algorithm into an O(n^3) time algorithm. Without memoization, the natural recursive algorithm runs in the exponential time since solved subproblems are repeatedly solved.

## The Memoization Algorithm Explained

A memoize recursive algorithm maintains an entry in a table for the solution to each subproblem. Each table entry initially contains a unique value to show that the entry has yet to be filled. When the subproblem encountered as the recursive algorithm unfolds, its solution is computed and then stored in the table. Each subsequent time we deal with this subproblem, we merely look up the value stored in the table and return it.

Steps involved in memoization algorithm: -

1. Identify a sub-problem.
2. Store the sub-problem in the data structure.
3. Create a cache data structure for the function results

Whenever you call a function, return the cached results. Start calling the function to compute the missing result and then update the cache before returning to the caller. Sufficient cache storage guarantees that the function resulting for a specific set of function arguments will compute more than once. Once you get a cached result, stop re-running the memorize function for the same set of inputs. Instead, fetch the cached result and return it, anyway.

<

## Tags  #### KnowledgeHut

Author
KnowledgeHut is an outcome-focused global ed-tech company. We help organizations and professionals unlock excellence through skills development. We offer training solutions under the people and process, data science, full-stack development, cybersecurity, future technologies and digital transformation verticals.