Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
0% found this document useful (0 votes)
2 views

Python Tutorial_ Memoization and Decorators

The document provides an overview of memoization, a technique used in computing to optimize function calls by storing previously computed results. It explains how to implement memoization using decorators in Python, allowing for improved performance without altering the original function's clarity. Additionally, it includes examples and exercises related to memoization and its applications in programming.

Uploaded by

Sentinel
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
2 views

Python Tutorial_ Memoization and Decorators

The document provides an overview of memoization, a technique used in computing to optimize function calls by storing previously computed results. It explains how to implement memoization using decorators in Python, allowing for improved performance without altering the original function's clarity. Additionally, it includes examples and exercises related to memoization and its applications in programming.

Uploaded by

Sentinel
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 1

Python Course

Home Python 2 Tutorial Python 3 Tutorial Advanced Topics Numerical Programming Machine Learning Tkinter Tutorial Contact

Previous Chapter: Decorators


Next Chapter: Read and Write Files

Memoization with Decorators

Follow Bernd Klein,


Definition of Memoization the author of this
website, at Google+:
Bernd Klein on
The term "memoization" was introduced by Donald Michie in the year 1968. It's based on the Latin word memorandum, meaning "to be remembered". It's not a
Python 3 misspelling of the word memorization, though in a way it has something in common. Memoisation is a technique used in computing to speed up programs. This is
Google
Tutorial accomplished by memorizing the calculation results of processed input such as the results of function calls. If the same input or a function call with the same
Bernd Klein on
parameters is used, the previously stored results can be used again and unnecessary calculation are avoided. In many cases a simple array is used for storing the
The Origins of Facebook
results, but lots of other structures can be used as well, such as associative arrays, called hashes in Perl or dictionaries in Python.
Python
Starting with Memoization can be explicitly programmed by the programmer, but some programming languages like Python provide mechanisms to automatically memoize
Search this website:
Python: The functions.
Interactive Shell
Go
Executing a
Script Memoization with Function Decorators
This topic in German
Indentation / Deutsche
You may consult our chapter on decorators as well. Especially, if you may have problems in understanding our reasoning.
Data Types and Übersetzung:
Variables Memoisation und
In our previous chapter about recursive functions, we worked out an iterative and a recursive version to calculate the Fibonacci numbers. We have shown that a direct implementation of the mathematical definition
Operators into a recursive function like the following has an exponential runtime behaviour: Dekorateure
Sequential Data
Types: Lists and def fib(n): Python 3
if n == 0:
Strings
return 0
List elif n == 1: This is a tutorial in
Manipulations return 1 Python3, but this
Shallow and else: chapter of our course
return fib(n-1) + fib(n-2) is available in a
Deep Copy
version for Python
Dictionaries
2.x as well:
Sets and Frozen We also presented a way to improve the runtime behaviour of the recursive version by adding a dictionary to memorize previously calculated values of the function. This is an example of explicitly using the Memoization and
Sets technique of memoization, but we didn't call it like this. The disadvantage of this method is that the clarity and the beauty of the original recursive implementation is lost. Decorators in Python
An Extensive 2.x
Example Using The "problem" is that we changed the code of the recursive fib function. The following code doesn't change our fib function, so that its clarity and legibility isn't touched. To this purpose, we define and use a function
Sets which we call memoize. memoize() takes a function as an argument. The function memoize uses a dictionary "memo" to store the function results. Though the variable "memo" as well as the function "f" are local to Book a
memoize, they are captured by a closure through the helper function which is returned as a reference by memoize(). So, the call memoize(fib) returns a reference to the helper() which is doing what fib() would do
input via the Dedicated
on its own plus a wrapper which saves the calculated results. For an integer 'n' fib(n) will only be called, if n is not in the memo dictionary. If it is in it, we can output memo[n] as the result of fib(n).
keyboard Course
Conditional
Statements def memoize(f): The goal of this
Loops, while memo = {} website is to provide
def helper(x): educational material,
Loop
if x not in memo: allowing you to learn
For Loops memo[x] = f(x)
Python on your own.
Difference return memo[x]
return helper Nevertheless, it is
between faster and more
interators und efficient to attend a
Iterables def fib(n): "real" Python course
Output with Print if n == 0: in a classroom, with
Formatted output return 0 an experienced
elif n == 1: trainer. So why not
with string return 1
modulo and the attend one of the live
else:
return fib(n-1) + fib(n-2) Python courses
format method
Functions
fib = memoize(fib)
Recursion and
Recursive print(fib(40))
Functions
Parameter
Passing in
Let's look at the line in our code where we call memoize with fib as the argument:
Functions
Namespaces fib = memoize(fib)
Global and Local
Variables Doing this, we turn memoize into a decorator. One says that the fib function is decorated by the memoize() function.
Decorators We will illustrate with the following diagrams how the decoration is accomplished. The first diagram illustrates the state before the decoration, i.e. before we call fib = memoize(fib). We can see the function names
referencing their bodies: in Paris, London,
Memoization with
Berlin, Munich or
Decorators
Lake Constance by
Read and Write Bernd Klein, the
Files author of this
Modular tutorial?
Programming
and Modules
Packages in Onsite Training
Python Courses
Regular
Expressions Let us come to your
Regular company or institute
Expressions, and train your
employees, as we've
Advanced
done it many times in
Lambda
Amsterdam (The
Operator, Filter, Netherlands), Berlin
Reduce and Map (Germany), Bern
List (Switzerland), Basel
Comprehension (Switzerland), Zurich
Iterators and (Switzerland),
After having executed fib = memoize(fib) fib points to the body of the helper function, which had been returned by memoize. We can also perceive that the code of the original fib function can from now on only be Locarno
Generators reached via the "f" function of the helper function. There is no other way anymore to call the original fib directly, i.e. there is no other reference to it. The decorated Fibonacci function is called in the return (Switzerland), Den
Exception statement return fib(n-1) + fib(n-2), this means the code of the helper function which had been returned by memoize: Haag (The Hague),
Handling
Hamburg (Germany),
Tests, DocTests, Frankfurt (Germany),
UnitTests Toronto (Canada),
Object Oriented Edmonton (Canada),
Programming Munich (Germany)
Class and and many other
Instance cities. We do training
Attributes courses in England,
Switzerland,
Properties vs.
Liechtenstein,
getters and
Austria, Germany,
setters France, Belgium, the
Inheritance Netherlands,
Multiple Luxembourg, Poland,
Inheritance UK, Italy and other
Magic Methods locations in Europe
and Operator and in Canada.
Overloading
This way you will get
OOP, Inheritance
a perfect training up
Example to your needs and it
Slots will be extremely cost
Classes and efficient as well.
Class Creation Contact us so we can
Road to define and find the
Metaclasses best course
Metaclasses curriculum to meet
your needs, and
Metaclass Use
schedule course
Case: Count
sessions to be held at
Function Calls your location.
Abstract Classes

Skilled Python
Memory Programmers

Some funny or You can hire skilled


interesting things Python programmers
about memory, i.e. or even a skilled
"our" memory not team of Python
the one from the developers to work
computer: exclusively on your
"Why is it that our project. Contact us, if
memory is good you want more
enough to retain the information.
least triviality that
happens to us, and
Quote of the
yet not good enough
Day:
to recollect how often
we have told it to the
same person?" "At least for the
(Francois de La people who send me
Rochefoucauld, 1613 mail about a new
- 1680) language that they're
designing, the
"Nothing fixes a thing general advice is: do
so intensely in the it to learn about how
memory as the wish to write a compiler. "
Another point in the context of decorators deserves special mention: We don't usually write a decorator for just one use case or function. We rather use it multiple times for different functions. So we could imagine
to forget it." (Michel (Dennis Ritchie)
having further functions func1, func2, func3 and so on, which consume also a lot of time. Therefore, it makes sense to decorate each one with our decorator function "memoize":
de Montaigne, 1533 -
1592) fib = memoize(fib)
func1 = memoize(func1)
func2 = memoize(func2)
"It's a poor sort of
func3 = memoize(func3)
memory that only # and so on
works backward." Data Protection
(Lewis Carrol, 1879 - Declaration
1898)
Data Protection
We haven't used the Pythonic way of writing a decorator. Instead of writing the statement
Declaration
fib = memoize(fib)

we should have "decorated" our fib function with:


Bachet
@memoize

Claude Gaspard But this line has to be directly in front of the decorated function, in our example fib(). The complete example in a Pythonic way looks like this now:
Bachet de Méziriac
was a French Jesuit
and a poet, scholar def memoize(f):
and mathematician. memo = {}
He was born at Bourg def helper(x):
in 1581, and died in if x not in memo:
memo[x] = f(x)
1638. He wrote the
return memo[x]
Problèmes plaisants, return helper
of which the first
edition was issued in @memoize
1612, a second and def fib(n):
enlarged edition was if n == 0:
brought out in 1624; return 0
elif n == 1:
this contains an
return 1
interesting collection else:
of arithmetical tricks return fib(n-1) + fib(n-2)
and questions.
print(fib(40))
In his collection of
"Amusing and
Delightful Number
Problems"
("Problèmes plaisants Using a Callable Class for Memoization
& délectables qui se
font par les This subchapter can be skipped without problems by those who don't know about object orientation so far.
nombres") he had
the puzzle We can encapsulate the caching of the results in a class as well, as you can see in the following example:
(number154), which
we use in our main class Memoize:
text:
"Etant donnée telle def __init__(self, fn):
quantité qu'on self.fn = fn
self.memo = {}
voudra pesant un
nombre de livres def __call__(self, *args):
depuis 1 jusques à if args not in self.memo:
40 inclusivement self.memo[args] = self.fn(*args)
(sans toutefois return self.memo[args]
admettre les
fractions), on @Memoize
demande combien de def fib(n):
if n == 0:
poids pour le moins il
return 0
faudrait employer à elif n == 1:
cet effet" return 1
(English translation: else:
"We are looking for return fib(n-1) + fib(n-2)
the minimum number
of weights to be used
on a scale to weigh As we are using a dictionary, we can't use mutable arguments, i.e. the arguments have to be immutable.
an arbitrary number
of pounds from 1 to
40 inclusive, without Exercise
admitting fractions.)
This website is 1. Our exercise is an old riddle, going back to 1612. The French Jesuit Claude-Gaspar Bachet phrased it. We have to weigh quantities (e.g. sugar or flour) from 1
supported by: to 40 pounds. What is the least number of weights that can be used on a balance scale to way any of these quantities.

Linux and Python The first idea might be to use weights of 1, 2, 4, 8, 16 and 32 pounds. This is a minimal number, if we restrict ourself to put weights on one side and the stuff,
Courses and e.g. the sugar, on the other side. But it is possible to put weights on both pans of the scale. Now, we need only four weights, i.e. 1, 3, 9, 27
Seminars
Write a Python function weigh(), which calculates the weights needed and their distribution on the pans to weigh any amount from 1 to 40.

Solution

1. We need the function linear_combination() from our chapter "Linear Combinations".

def factors_set():
factors_set = ( (i, j, k, l) for i in [-1, 0, 1]
for j in [-1, 0, 1]
for k in [-1, 0, 1]
for l in [-1, 0, 1])
for factor in factors_set:
yield factor

def memoize(f):
results = {}
def helper(n):
if n not in results:
results[n] = f(n)
return results[n]
return helper

@memoize
def linear_combination(n):
""" returns the tuple (i,j,k,l) satisfying
n = i*1 + j*3 + k*9 + l*27 """
weighs = (1,3,9,27)

for factors in factors_set():


sum = 0
for i in range(len(factors)):
sum += factors[i] * weighs[i]
if sum == n:
return factors

With this, it is easy to write our function weigh().

def weigh(pounds):
weights = (1, 3, 9, 27)
scalars = linear_combination(pounds)
left = ""
right = ""
for i in range(len(scalars)):
if scalars[i] == -1:
left += str(weights[i]) + " "
elif scalars[i] == 1:
right += str(weights[i]) + " "
return (left,right)

for i in [2, 3, 4, 7, 8, 9, 20, 40]:


pans = weigh(i)
print("Left pan: " + str(i) + " plus " + pans[0])
print("Right pan: " + pans[1] + "\n")

Previous Chapter: Decorators


Next Chapter: Read and Write Files

© 2011 - 2018, Bernd Klein, Bodenseo; Design by Denise Mitchinson adapted for python-course.eu by Bernd Klein

You might also like