Jump to content

Archive:Think Python/Dictionaries: Difference between revisions

From IdeaWazaWiki
wikademia>Whiteknight
m Think Python: Automatically uploading HTML source of this book from http://www.greenteapress.com/thinkpython/html/. Will convert to wikitext in a separate step
 
wikademia>Whiteknight
m Partial (mostly) conversion from HTML to Wikitext
Line 1: Line 1:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
{{Think Python/Page}}
            "http://www.w3.org/TR/REC-html40/loose.dtd">
<HTML>
<HEAD>


<META http-equiv="Content-Type" content="text/html; charset=US-ASCII">
== Chapter&#XA0;11&#XA0;&#XA0;Dictionaries ==
<META name="GENERATOR" content="hevea 1.10">
 
<LINK rel="stylesheet" type="text/css" href="book.css">
 
<TITLE>Dictionaries</TITLE>
 
</HEAD>
 
<BODY >
 
<A HREF="book011.html"><IMG SRC="previous_motif.gif" ALT="Previous"></A>
 
<A HREF="index.html"><IMG SRC="contents_motif.gif" ALT="Up"></A>
 
<A HREF="book013.html"><IMG SRC="next_motif.gif" ALT="Next"></A>
 
<HR>
 
<H1 CLASS="chapter"><A NAME="htoc132"><FONT COLOR=black><FONT SIZE=3>Chapter&#XA0;11</FONT></FONT></A><FONT COLOR=black><FONT SIZE=3>&#XA0;&#XA0;Dictionaries</FONT></FONT></H1><P><FONT COLOR=black><FONT SIZE=3>
 
</FONT></FONT><A NAME="@default903"></A></P><P><A NAME="@default904"></A><FONT COLOR=black><FONT SIZE=3>
A '''dictionary''' is like a list, but more general. In a list,
</FONT></FONT><A NAME="@default905"></A><FONT COLOR=black><FONT SIZE=3>
</FONT></FONT><A NAME="@default906"></A><FONT COLOR=black><FONT SIZE=3>
</FONT></FONT><A NAME="@default907"></A><FONT COLOR=black><FONT SIZE=3>
</FONT></FONT><A NAME="@default908"></A></P><P><FONT COLOR=black><FONT SIZE=3>A </FONT></FONT><FONT COLOR=black><FONT SIZE=3><B>dictionary</B></FONT></FONT><FONT COLOR=black><FONT SIZE=3> is like a list, but more general. In a list,
the indices have to be integers; in a dictionary they can
the indices have to be integers; in a dictionary they can
be (almost) any type.</FONT></FONT></P><P><FONT COLOR=black><FONT SIZE=3>You can think of a dictionary as a mapping between a set of indices
be (almost) any type.
(which are called </FONT></FONT><FONT COLOR=black><FONT SIZE=3><B>keys</B></FONT></FONT><FONT COLOR=black><FONT SIZE=3>) and a set of values. Each key maps to a
 
value. The association of a key and a value is called a </FONT></FONT><FONT COLOR=black><FONT SIZE=3><B>key-value pair</B></FONT></FONT><FONT COLOR=black><FONT SIZE=3> or sometimes an </FONT></FONT><FONT COLOR=black><FONT SIZE=3><B>item</B></FONT></FONT><FONT COLOR=black><FONT SIZE=3>.</FONT></FONT></P><P><FONT COLOR=black><FONT SIZE=3>As an example, we&#X2019;ll build a dictionary that maps from English
You can think of a dictionary as a mapping between a set of indices
to Spanish words, so the keys and the values are all strings.</FONT></FONT></P><P><FONT COLOR=black><FONT SIZE=3>The function </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>dict</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> creates a new dictionary with no items.
(which are called '''keys''') and a set of values. Each key maps to a
Because </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>dict</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> is the name of a built-in function, you
value. The association of a key and a value is called a '''key-value pair''' or sometimes an '''item'''.
should avoid using it as a variable name.</FONT></FONT></P><P><A NAME="@default909"></A><FONT COLOR=black><FONT SIZE=3>
 
</FONT></FONT><A NAME="@default910"></A></P><PRE CLASS="verbatim"><FONT COLOR=blue><FONT SIZE=4>&gt;&gt;&gt; eng2sp = dict()
As an example, we&#X2019;ll build a dictionary that maps from English
to Spanish words, so the keys and the values are all strings.
 
The function <TT>dict</TT> creates a new dictionary with no items.
Because <TT>dict</TT> is the name of a built-in function, you
should avoid using it as a variable name.
 
 
 
<PRE CLASS="verbatim">&gt;&gt;&gt; eng2sp = dict()
&gt;&gt;&gt; print eng2sp
&gt;&gt;&gt; print eng2sp
{}
{}
</FONT></FONT></PRE><P><FONT COLOR=black><FONT SIZE=3>The squiggly-brackets, </FONT></FONT><CODE><FONT COLOR=black><FONT SIZE=3>{}</FONT></FONT></CODE><FONT COLOR=black><FONT SIZE=3>, represent an empty dictionary.
</PRE>
To add items to the dictionary, you can use square brackets:</FONT></FONT></P><P><A NAME="@default911"></A><FONT COLOR=black><FONT SIZE=3>
The squiggly-brackets, <CODE>{}</CODE>, represent an empty dictionary.
</FONT></FONT><A NAME="@default912"></A></P><PRE CLASS="verbatim"><FONT COLOR=blue><FONT SIZE=4>&gt;&gt;&gt; eng2sp['one'] = 'uno'
To add items to the dictionary, you can use square brackets:
</FONT></FONT></PRE><P><FONT COLOR=black><FONT SIZE=3>This line creates an item that maps from the key
 
</FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>&#X2019;one&#X2019;</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> to the value </FONT></FONT><CODE><FONT COLOR=black><FONT SIZE=3>'uno'</FONT></FONT></CODE><FONT COLOR=black><FONT SIZE=3>. If we print the
 
 
<PRE CLASS="verbatim">&gt;&gt;&gt; eng2sp['one'] = 'uno'
</PRE>
This line creates an item that maps from the key
<TT>&#X2019;one&#X2019;</TT> to the value <CODE>'uno'</CODE>. If we print the
dictionary again, we see a key-value pair with a colon
dictionary again, we see a key-value pair with a colon
between the key and value:</FONT></FONT></P><PRE CLASS="verbatim"><FONT COLOR=blue><FONT SIZE=4>&gt;&gt;&gt; print eng2sp
between the key and value:
<PRE CLASS="verbatim">&gt;&gt;&gt; print eng2sp
{'one': 'uno'}
{'one': 'uno'}
</FONT></FONT></PRE><P><FONT COLOR=black><FONT SIZE=3>This output format is also an input format. For example,
</PRE>
you can create a new dictionary with three items:</FONT></FONT></P><PRE CLASS="verbatim"><FONT COLOR=blue><FONT SIZE=4>&gt;&gt;&gt; eng2sp = {'one': 'uno', 'two': 'dos', 'three': 'tres'}
This output format is also an input format. For example,
</FONT></FONT></PRE><P><FONT COLOR=black><FONT SIZE=3>But if you print </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>eng2sp</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3>, you might be surprised:</FONT></FONT></P><PRE CLASS="verbatim"><FONT COLOR=blue><FONT SIZE=4>&gt;&gt;&gt; print eng2sp
you can create a new dictionary with three items:
<PRE CLASS="verbatim">&gt;&gt;&gt; eng2sp = {'one': 'uno', 'two': 'dos', 'three': 'tres'}
</PRE>
But if you print <TT>eng2sp</TT>, you might be surprised:
<PRE CLASS="verbatim">&gt;&gt;&gt; print eng2sp
{'one': 'uno', 'three': 'tres', 'two': 'dos'}
{'one': 'uno', 'three': 'tres', 'two': 'dos'}
</FONT></FONT></PRE><P><FONT COLOR=black><FONT SIZE=3>The order of the key-value pairs is not the same. In fact, if
</PRE>
The order of the key-value pairs is not the same. In fact, if
you type the same example on your computer, you might get a
you type the same example on your computer, you might get a
different result. In general, the order of items in
different result. In general, the order of items in
a dictionary is unpredictable.</FONT></FONT></P><P><FONT COLOR=black><FONT SIZE=3>But that&#X2019;s not a problem because
a dictionary is unpredictable.
 
But that&#X2019;s not a problem because
the elements of a dictionary are never indexed with integer indices.
the elements of a dictionary are never indexed with integer indices.
Instead, you use the keys to look up the corresponding values:</FONT></FONT></P><PRE CLASS="verbatim"><FONT COLOR=blue><FONT SIZE=4>&gt;&gt;&gt; print eng2sp['two']
Instead, you use the keys to look up the corresponding values:
<PRE CLASS="verbatim">&gt;&gt;&gt; print eng2sp['two']
'dos'
'dos'
</FONT></FONT></PRE><P><FONT COLOR=black><FONT SIZE=3>The key </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>&#X2019;two&#X2019;</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> always maps to the value </FONT></FONT><CODE><FONT COLOR=black><FONT SIZE=3>'dos'</FONT></FONT></CODE><FONT COLOR=black><FONT SIZE=3> so the order
</PRE>
of the items doesn&#X2019;t matter.</FONT></FONT></P><P><FONT COLOR=black><FONT SIZE=3>If the key isn&#X2019;t in the dictionary, you get an exception:</FONT></FONT></P><P><A NAME="@default913"></A><FONT COLOR=black><FONT SIZE=3>
The key <TT>&#X2019;two&#X2019;</TT> always maps to the value <CODE>'dos'</CODE> so the order
</FONT></FONT><A NAME="@default914"></A></P><PRE CLASS="verbatim"><FONT COLOR=blue><FONT SIZE=4>&gt;&gt;&gt; print eng2sp['four']
of the items doesn&#X2019;t matter.
 
If the key isn&#X2019;t in the dictionary, you get an exception:
 
 
 
<PRE CLASS="verbatim">&gt;&gt;&gt; print eng2sp['four']
KeyError: 'four'
KeyError: 'four'
</FONT></FONT></PRE><P><FONT COLOR=black><FONT SIZE=3>The </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>len</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> function works on dictionaries; it returns the
</PRE>
number of key-value pairs:</FONT></FONT></P><P><A NAME="@default915"></A><FONT COLOR=black><FONT SIZE=3>
The <TT>len</TT> function works on dictionaries; it returns the
</FONT></FONT><A NAME="@default916"></A></P><PRE CLASS="verbatim"><FONT COLOR=blue><FONT SIZE=4>&gt;&gt;&gt; len(eng2sp)
number of key-value pairs:
 
 
 
<PRE CLASS="verbatim">&gt;&gt;&gt; len(eng2sp)
3
3
</FONT></FONT></PRE><P><FONT COLOR=black><FONT SIZE=3>The </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>in</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> operator works on dictionaries; it tells you whether
</PRE>
something appears as a </FONT></FONT><FONT COLOR=black><FONT SIZE=3><EM>key</EM></FONT></FONT><FONT COLOR=black><FONT SIZE=3> in the dictionary (appearing
The <TT>in</TT> operator works on dictionaries; it tells you whether
as a value is not good enough).</FONT></FONT></P><P><A NAME="@default917"></A><FONT COLOR=black><FONT SIZE=3>
something appears as a ''key'' in the dictionary (appearing
</FONT></FONT><A NAME="@default918"></A><FONT COLOR=black><FONT SIZE=3>
as a value is not good enough).
</FONT></FONT><A NAME="@default919"></A></P><PRE CLASS="verbatim"><FONT COLOR=blue><FONT SIZE=4>&gt;&gt;&gt; 'one' in eng2sp
 
 
 
 
<PRE CLASS="verbatim">&gt;&gt;&gt; 'one' in eng2sp
True
True
&gt;&gt;&gt; 'uno' in eng2sp
&gt;&gt;&gt; 'uno' in eng2sp
False
False
</FONT></FONT></PRE><P><FONT COLOR=black><FONT SIZE=3>To see whether something appears as a value in a dictionary, you
</PRE>
can use the method </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>values</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3>, which returns the values as
To see whether something appears as a value in a dictionary, you
a list, and then use the </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>in</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> operator:</FONT></FONT></P><P><A NAME="@default920"></A><FONT COLOR=black><FONT SIZE=3>
can use the method <TT>values</TT>, which returns the values as
</FONT></FONT><A NAME="@default921"></A></P><PRE CLASS="verbatim"><FONT COLOR=blue><FONT SIZE=4>&gt;&gt;&gt; vals = eng2sp.values()
a list, and then use the <TT>in</TT> operator:
 
 
 
<PRE CLASS="verbatim">&gt;&gt;&gt; vals = eng2sp.values()
&gt;&gt;&gt; 'uno' in vals
&gt;&gt;&gt; 'uno' in vals
True
True
</FONT></FONT></PRE><P><FONT COLOR=black><FONT SIZE=3>The </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>in</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> operator uses different algorithms for lists and
</PRE>
The <TT>in</TT> operator uses different algorithms for lists and
dictionaries. For lists, it uses a search algorithm, as in
dictionaries. For lists, it uses a search algorithm, as in
Section&#XA0;</FONT></FONT><A HREF="book009.html#find"><FONT COLOR=black><FONT SIZE=3>8.6</FONT></FONT></A><FONT COLOR=black><FONT SIZE=3>. As the list gets longer, the search time gets
Section&#XA0;8.6. As the list gets longer, the search time gets
longer in direct proportion. For dictionaries, Python uses an
longer in direct proportion. For dictionaries, Python uses an
algorithm called a </FONT></FONT><FONT COLOR=black><FONT SIZE=3><B>hashtable</B></FONT></FONT><FONT COLOR=black><FONT SIZE=3> that has a remarkable property: the
algorithm called a '''hashtable''' that has a remarkable property: the
</FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>in</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> operator takes about the same amount of time no matter how
<TT>in</TT> operator takes about the same amount of time no matter how
many items there are in a dictionary. I won&#X2019;t explain how that&#X2019;s
many items there are in a dictionary. I won&#X2019;t explain how that&#X2019;s
possible, but you can read more about it at
possible, but you can read more about it at
</FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>wikipedia.org/wiki/Hash_table</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3>.</FONT></FONT></P><P><A NAME="@default922"></A></P><DIV CLASS="theorem"><FONT COLOR=black><FONT SIZE=3><B>Exercise&#XA0;1</B></FONT></FONT><FONT COLOR=black><FONT SIZE=3>&#XA0;&#XA0;<EM>
<TT>wikipedia.org/wiki/Hash_table</TT>.
</EM></FONT></FONT><A NAME="wordlist2"></A><P><A NAME="@default923"></A><FONT COLOR=black><FONT SIZE=3><EM>
 
</EM></FONT></FONT><A NAME="@default924"></A></P><P><FONT COLOR=black><FONT SIZE=3><EM>Write a function that reads the words in </EM></FONT></FONT><FONT COLOR=black><FONT SIZE=3><EM><TT>words.txt</TT></EM></FONT></FONT><FONT COLOR=black><FONT SIZE=3><EM> and
<DIV CLASS="theorem">'''Exercise&#XA0;1'''&#XA0;&#XA0;''
''
''
''
 
''Write a function that reads the words in ''''<TT>words.txt</TT>'''' and
stores them as keys in a dictionary. It doesn&#X2019;t matter what the
stores them as keys in a dictionary. It doesn&#X2019;t matter what the
values are. Then you can use the </EM></FONT></FONT><FONT COLOR=black><FONT SIZE=3><EM><TT>in</TT></EM></FONT></FONT><FONT COLOR=black><FONT SIZE=3><EM> operator
values are. Then you can use the ''''<TT>in</TT>'''' operator
as a fast way to check whether a string is in
as a fast way to check whether a string is in
the dictionary.</EM></FONT></FONT></P><P><FONT COLOR=black><FONT SIZE=3><EM>If you did Exercise&#XA0;</EM></FONT></FONT><A HREF="book011.html#wordlist1"><FONT COLOR=black><FONT SIZE=3><EM>10.8</EM></FONT></FONT></A><FONT COLOR=black><FONT SIZE=3><EM>, you can compare the speed
the dictionary.''
of this implementation with the list </EM></FONT></FONT><FONT COLOR=black><FONT SIZE=3><EM><TT>in</TT></EM></FONT></FONT><FONT COLOR=black><FONT SIZE=3><EM> operator and the
 
bisection search.</EM></FONT></FONT></P></DIV><H2 CLASS="section"><A NAME="toc120"></A><A NAME="htoc133"><FONT COLOR=black><FONT SIZE=3>11.1</FONT></FONT></A><FONT COLOR=black><FONT SIZE=3>&#XA0;&#XA0;Dictionary as a set of counters</FONT></FONT></H2><P><FONT COLOR=black><FONT SIZE=3>
''If you did Exercise&#XA0;''''10.8'''', you can compare the speed
</FONT></FONT><A NAME="histogram"></A></P><P><A NAME="@default925"></A></P><P><FONT COLOR=black><FONT SIZE=3>Suppose you are given a string and you want to count how many
of this implementation with the list ''''<TT>in</TT>'''' operator and the
times each letter appears. There are several ways you could do it:</FONT></FONT></P><OL CLASS="enumerate" type=1><LI CLASS="li-enumerate"><FONT COLOR=black><FONT SIZE=3>You could create 26 variables, one for each letter of the
bisection search.''
</DIV>=== 11.1&#XA0;&#XA0;Dictionary as a set of counters ===
 
 
 
 
Suppose you are given a string and you want to count how many
times each letter appears. There are several ways you could do it:
 
*You could create 26 variables, one for each letter of the
alphabet. Then you could traverse the string and, for each
alphabet. Then you could traverse the string and, for each
character, increment the corresponding counter, probably using
character, increment the corresponding counter, probably using
a chained conditional.</FONT></FONT></LI><LI CLASS="li-enumerate"><FONT COLOR=black><FONT SIZE=3>You could create a list with 26 elements. Then you could
a chained conditional.
 
*You could create a list with 26 elements. Then you could
convert each character to a number (using the built-in function
convert each character to a number (using the built-in function
</FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>ord</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3>), use the number as an index into the list, and increment
<TT>ord</TT>), use the number as an index into the list, and increment
the appropriate counter.</FONT></FONT></LI><LI CLASS="li-enumerate"><FONT COLOR=black><FONT SIZE=3>You could create a dictionary with characters as keys
the appropriate counter.
 
*You could create a dictionary with characters as keys
and counters as the corresponding values. The first time you
and counters as the corresponding values. The first time you
see a character, you would add an item to the dictionary. After
see a character, you would add an item to the dictionary. After
that you would increment the value of an existing item.</FONT></FONT></LI></OL><P><FONT COLOR=black><FONT SIZE=3>Each of these options performs the same computation, but each
that you would increment the value of an existing item.
of them implements that computation in a different way.</FONT></FONT></P><P><A NAME="@default926"></A></P><P><FONT COLOR=black><FONT SIZE=3>An </FONT></FONT><FONT COLOR=black><FONT SIZE=3><B>implementation</B></FONT></FONT><FONT COLOR=black><FONT SIZE=3> is a way of performing a computation;
 
Each of these options performs the same computation, but each
of them implements that computation in a different way.
 
An '''implementation''' is a way of performing a computation;
some implementations are better than others. For example,
some implementations are better than others. For example,
an advantage of the dictionary implementation is that we don&#X2019;t
an advantage of the dictionary implementation is that we don&#X2019;t
have to know ahead of time which letters appear in the string
have to know ahead of time which letters appear in the string
and we only have to make room for the letters that do appear.</FONT></FONT></P><P><FONT COLOR=black><FONT SIZE=3>Here is what the code might look like:</FONT></FONT></P><PRE CLASS="verbatim"><FONT COLOR=blue><FONT SIZE=4>def histogram(s):
and we only have to make room for the letters that do appear.
 
Here is what the code might look like:
<PRE CLASS="verbatim">def histogram(s):
     d = dict()
     d = dict()
     for c in s:
     for c in s:
Line 111: Line 171:
             d[c] += 1
             d[c] += 1
     return d
     return d
</FONT></FONT></PRE><P><FONT COLOR=black><FONT SIZE=3>The name of the function is </FONT></FONT><FONT COLOR=black><FONT SIZE=3><B>histogram</B></FONT></FONT><FONT COLOR=black><FONT SIZE=3>, which is a statistical
</PRE>
term for a set of counters (or frequencies).</FONT></FONT></P><P><A NAME="@default927"></A><FONT COLOR=black><FONT SIZE=3>
The name of the function is '''histogram''', which is a statistical
</FONT></FONT><A NAME="@default928"></A><FONT COLOR=black><FONT SIZE=3>
term for a set of counters (or frequencies).
</FONT></FONT><A NAME="@default929"></A></P><P><FONT COLOR=black><FONT SIZE=3>The first line of the
 
function creates an empty dictionary. The </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>for</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> loop traverses
 
the string. Each time through the loop, if the character </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>c</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> is
 
not in the dictionary, we create a new item with key </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>c</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> and the
 
initial value 1 (since we have seen this letter once). If </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>c</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> is
 
already in the dictionary we increment </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>d[c]</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3>.</FONT></FONT></P><P><A NAME="@default930"></A></P><P><FONT COLOR=black><FONT SIZE=3>Here&#X2019;s how it works:</FONT></FONT></P><PRE CLASS="verbatim"><FONT COLOR=blue><FONT SIZE=4>&gt;&gt;&gt; h = histogram('brontosaurus')
The first line of the
function creates an empty dictionary. The <TT>for</TT> loop traverses
the string. Each time through the loop, if the character <TT>c</TT> is
not in the dictionary, we create a new item with key <TT>c</TT> and the
initial value 1 (since we have seen this letter once). If <TT>c</TT> is
already in the dictionary we increment <TT>d[c]</TT>.
 
Here&#X2019;s how it works:
<PRE CLASS="verbatim">&gt;&gt;&gt; h = histogram('brontosaurus')
&gt;&gt;&gt; print h
&gt;&gt;&gt; print h
{'a': 1, 'b': 1, 'o': 2, 'n': 1, 's': 2, 'r': 2, 'u': 2, 't': 1}
{'a': 1, 'b': 1, 'o': 2, 'n': 1, 's': 2, 'r': 2, 'u': 2, 't': 1}
</FONT></FONT></PRE><P><FONT COLOR=black><FONT SIZE=3>The histogram indicates that the letters </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>&#X2019;a&#X2019;</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> and </FONT></FONT><CODE><FONT COLOR=black><FONT SIZE=3>'b'</FONT></FONT></CODE><FONT COLOR=black><FONT SIZE=3>
</PRE>
appear once; </FONT></FONT><CODE><FONT COLOR=black><FONT SIZE=3>'o'</FONT></FONT></CODE><FONT COLOR=black><FONT SIZE=3> appears twice, and so on.</FONT></FONT></P><DIV CLASS="theorem"><FONT COLOR=black><FONT SIZE=3><B>Exercise&#XA0;2</B></FONT></FONT><FONT COLOR=black><FONT SIZE=3>&#XA0;&#XA0;</FONT></FONT><P><A NAME="@default931"></A><FONT COLOR=black><FONT SIZE=3><EM>
The histogram indicates that the letters <TT>&#X2019;a&#X2019;</TT> and <CODE>'b'</CODE>
</EM></FONT></FONT><A NAME="@default932"></A></P><P><FONT COLOR=black><FONT SIZE=3><EM>Dictionaries have a method called </EM></FONT></FONT><FONT COLOR=black><FONT SIZE=3><EM><TT>get</TT></EM></FONT></FONT><FONT COLOR=black><FONT SIZE=3><EM> that takes a key
appear once; <CODE>'o'</CODE> appears twice, and so on.
<DIV CLASS="theorem">'''Exercise&#XA0;2'''&#XA0;&#XA0;
''
''
 
''Dictionaries have a method called ''''<TT>get</TT>'''' that takes a key
and a default value. If the key appears in the dictionary,
and a default value. If the key appears in the dictionary,
</EM></FONT></FONT><FONT COLOR=black><FONT SIZE=3><EM><TT>get</TT></EM></FONT></FONT><FONT COLOR=black><FONT SIZE=3><EM> returns the corresponding value; otherwise it returns
''''<TT>get</TT>'''' returns the corresponding value; otherwise it returns
the default value. For example:</EM></FONT></FONT></P><PRE CLASS="verbatim"><EM><FONT COLOR=blue><FONT SIZE=4>&gt;&gt;&gt; h = histogram('a')
the default value. For example:''
<PRE CLASS="verbatim">''&gt;&gt;&gt; h = histogram('a')
&gt;&gt;&gt; print h
&gt;&gt;&gt; print h
{'a': 1}
{'a': 1}
Line 134: Line 208:
&gt;&gt;&gt; h.get('b', 0)
&gt;&gt;&gt; h.get('b', 0)
0
0
</FONT></FONT></EM></PRE><P><EM><FONT COLOR=black><FONT SIZE=3>Use </FONT></FONT></EM><EM><FONT COLOR=black><FONT SIZE=3><TT>get</TT></FONT></FONT></EM><EM><FONT COLOR=black><FONT SIZE=3> to write </FONT></FONT></EM><EM><FONT COLOR=black><FONT SIZE=3><TT>histogram</TT></FONT></FONT></EM><EM><FONT COLOR=black><FONT SIZE=3> more concisely. You
''</PRE>
should be able to eliminate the </FONT></FONT></EM><EM><FONT COLOR=black><FONT SIZE=3><TT>if</TT></FONT></FONT></EM><EM><FONT COLOR=black><FONT SIZE=3> statement.
''Use ''''<TT>get</TT>'''' to write ''''<TT>histogram</TT>'''' more concisely. You
</FONT></FONT></EM></P></DIV><H2 CLASS="section"><A NAME="toc121"></A><A NAME="htoc134"><FONT COLOR=black><FONT SIZE=3>11.2</FONT></FONT></A><FONT COLOR=black><FONT SIZE=3>&#XA0;&#XA0;Looping and dictionaries</FONT></FONT></H2><P><A NAME="@default933"></A><FONT COLOR=black><FONT SIZE=3>
should be able to eliminate the ''''<TT>if</TT>'''' statement.
</FONT></FONT><A NAME="@default934"></A><FONT COLOR=black><FONT SIZE=3>
''
</FONT></FONT><A NAME="@default935"></A></P><P><FONT COLOR=black><FONT SIZE=3>If you use a dictionary in a </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>for</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> statement, it traverses
</DIV>=== 11.2&#XA0;&#XA0;Looping and dictionaries ===
the keys of the dictionary. For example, </FONT></FONT><CODE><FONT COLOR=black><FONT SIZE=3>print_hist</FONT></FONT></CODE><FONT COLOR=black><FONT SIZE=3>
 
prints each key and the corresponding value:</FONT></FONT></P><PRE CLASS="verbatim"><FONT COLOR=blue><FONT SIZE=4>def print_hist(h):
 
 
 
 
If you use a dictionary in a <TT>for</TT> statement, it traverses
the keys of the dictionary. For example, <CODE>print_hist</CODE>
prints each key and the corresponding value:
<PRE CLASS="verbatim">def print_hist(h):
     for c in h:
     for c in h:
         print c, h[c]
         print c, h[c]
</FONT></FONT></PRE><P><FONT COLOR=black><FONT SIZE=3>Here&#X2019;s what the output looks like:</FONT></FONT></P><PRE CLASS="verbatim"><FONT COLOR=blue><FONT SIZE=4>&gt;&gt;&gt; h = histogram('parrot')
</PRE>
Here&#X2019;s what the output looks like:
<PRE CLASS="verbatim">&gt;&gt;&gt; h = histogram('parrot')
&gt;&gt;&gt; print_hist(h)
&gt;&gt;&gt; print_hist(h)
a 1
a 1
Line 150: Line 233:
t 1
t 1
o 1
o 1
</FONT></FONT></PRE><P><FONT COLOR=black><FONT SIZE=3>Again, the keys are in no particular order.</FONT></FONT></P><DIV CLASS="theorem"><FONT COLOR=black><FONT SIZE=3><B>Exercise&#XA0;3</B></FONT></FONT><FONT COLOR=black><FONT SIZE=3>&#XA0;&#XA0;</FONT></FONT><P><A NAME="@default936"></A><FONT COLOR=black><FONT SIZE=3><EM>
</PRE>
</EM></FONT></FONT><A NAME="@default937"></A></P><P><FONT COLOR=black><FONT SIZE=3><EM>Dictionaries have a method called </EM></FONT></FONT><FONT COLOR=black><FONT SIZE=3><EM><TT>keys</TT></EM></FONT></FONT><FONT COLOR=black><FONT SIZE=3><EM> that returns
Again, the keys are in no particular order.
the keys of the dictionary, in no particular order, as a list.</EM></FONT></FONT></P><P><FONT COLOR=black><FONT SIZE=3><EM>Modify </EM></FONT></FONT><CODE><FONT COLOR=black><FONT SIZE=3><EM>print_hist</EM></FONT></FONT></CODE><FONT COLOR=black><FONT SIZE=3><EM> to print the keys and their values
<DIV CLASS="theorem">'''Exercise&#XA0;3'''&#XA0;&#XA0;
''
''
 
''Dictionaries have a method called ''''<TT>keys</TT>'''' that returns
the keys of the dictionary, in no particular order, as a list.''
 
''Modify ''<CODE>''print_hist''</CODE>'' to print the keys and their values
in alphabetical order.
in alphabetical order.
</EM></FONT></FONT></P></DIV><H2 CLASS="section"><A NAME="toc122"></A><A NAME="htoc135"><FONT COLOR=black><FONT SIZE=3>11.3</FONT></FONT></A><FONT COLOR=black><FONT SIZE=3>&#XA0;&#XA0;Reverse lookup</FONT></FONT></H2><P><A NAME="@default938"></A><FONT COLOR=black><FONT SIZE=3>
''
</FONT></FONT><A NAME="@default939"></A><FONT COLOR=black><FONT SIZE=3>
</DIV>=== 11.3&#XA0;&#XA0;Reverse lookup ===
</FONT></FONT><A NAME="@default940"></A><FONT COLOR=black><FONT SIZE=3>
 
</FONT></FONT><A NAME="@default941"></A></P><P><FONT COLOR=black><FONT SIZE=3>Given a dictionary </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>d</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> and a key </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>k</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3>, it is easy to
 
find the corresponding value </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>v = d[k]</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3>. This operation
 
is called a </FONT></FONT><FONT COLOR=black><FONT SIZE=3><B>lookup</B></FONT></FONT><FONT COLOR=black><FONT SIZE=3>.</FONT></FONT></P><P><FONT COLOR=black><FONT SIZE=3>But what if you have </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>v</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> and you want to find </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>k</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3>?
 
 
 
Given a dictionary <TT>d</TT> and a key <TT>k</TT>, it is easy to
find the corresponding value <TT>v = d[k]</TT>. This operation
is called a '''lookup'''.
 
But what if you have <TT>v</TT> and you want to find <TT>k</TT>?
You have two problems: first, there might be more than one
You have two problems: first, there might be more than one
key that maps to the value </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>v</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3>. Depending on the application,
key that maps to the value <TT>v</TT>. Depending on the application,
you might be able to pick one, or you might have to make
you might be able to pick one, or you might have to make
a list that contains all of them. Second, there is no
a list that contains all of them. Second, there is no
simple syntax to do a </FONT></FONT><FONT COLOR=black><FONT SIZE=3><B>reverse lookup</B></FONT></FONT><FONT COLOR=black><FONT SIZE=3>; you have to search.</FONT></FONT></P><P><FONT COLOR=black><FONT SIZE=3>Here is a function that takes a value and returns the first
simple syntax to do a '''reverse lookup'''; you have to search.
key that maps to that value:</FONT></FONT></P><PRE CLASS="verbatim"><FONT COLOR=blue><FONT SIZE=4>def reverse_lookup(d, v):
 
Here is a function that takes a value and returns the first
key that maps to that value:
<PRE CLASS="verbatim">def reverse_lookup(d, v):
     for k in d:
     for k in d:
         if d[k] == v:
         if d[k] == v:
             return k
             return k
     raise ValueError
     raise ValueError
</FONT></FONT></PRE><P><FONT COLOR=black><FONT SIZE=3>This function is yet another example of the search pattern, but it
</PRE>
uses a feature we haven&#X2019;t seen before, </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>raise</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3>. The </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>raise</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3>
This function is yet another example of the search pattern, but it
statement causes an exception; in this case it causes a </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>ValueError</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3>, which generally indicates that there is something wrong
uses a feature we haven&#X2019;t seen before, <TT>raise</TT>. The <TT>raise</TT>
with the value of a parameter.</FONT></FONT></P><P><A NAME="@default942"></A><FONT COLOR=black><FONT SIZE=3>
statement causes an exception; in this case it causes a <TT>ValueError</TT>, which generally indicates that there is something wrong
</FONT></FONT><A NAME="@default943"></A><FONT COLOR=black><FONT SIZE=3>
with the value of a parameter.
</FONT></FONT><A NAME="@default944"></A><FONT COLOR=black><FONT SIZE=3>
 
</FONT></FONT><A NAME="@default945"></A><FONT COLOR=black><FONT SIZE=3>
 
</FONT></FONT><A NAME="@default946"></A><FONT COLOR=black><FONT SIZE=3>
 
</FONT></FONT><A NAME="@default947"></A></P><P><FONT COLOR=black><FONT SIZE=3>If we get to the end of the loop, that means </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>v</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3>
 
 
 
 
 
If we get to the end of the loop, that means <TT>v</TT>
doesn&#X2019;t appear in the dictionary as a value, so we raise an
doesn&#X2019;t appear in the dictionary as a value, so we raise an
exception.</FONT></FONT></P><P><FONT COLOR=black><FONT SIZE=3>Here is an example of a successful reverse lookup:</FONT></FONT></P><PRE CLASS="verbatim"><FONT COLOR=blue><FONT SIZE=4>&gt;&gt;&gt; h = histogram('parrot')
exception.
 
Here is an example of a successful reverse lookup:
<PRE CLASS="verbatim">&gt;&gt;&gt; h = histogram('parrot')
&gt;&gt;&gt; k = reverse_lookup(h, 2)
&gt;&gt;&gt; k = reverse_lookup(h, 2)
&gt;&gt;&gt; print k
&gt;&gt;&gt; print k
r
r
</FONT></FONT></PRE><P><FONT COLOR=black><FONT SIZE=3>And an unsuccessful one:</FONT></FONT></P><PRE CLASS="verbatim"><FONT COLOR=blue><FONT SIZE=4>&gt;&gt;&gt; k = reverse_lookup(h, 3)
</PRE>
And an unsuccessful one:
<PRE CLASS="verbatim">&gt;&gt;&gt; k = reverse_lookup(h, 3)
Traceback (most recent call last):
Traceback (most recent call last):
   File "&lt;stdin&gt;", line 1, in ?
   File "&lt;stdin&gt;", line 1, in ?
   File "&lt;stdin&gt;", line 5, in reverse_lookup
   File "&lt;stdin&gt;", line 5, in reverse_lookup
ValueError
ValueError
</FONT></FONT></PRE><P><FONT COLOR=black><FONT SIZE=3>The result when you raise an exception is the same as when
</PRE>
Python raises one: it prints a traceback and an error message.</FONT></FONT></P><P><A NAME="@default948"></A><FONT COLOR=black><FONT SIZE=3>
The result when you raise an exception is the same as when
</FONT></FONT><A NAME="@default949"></A><FONT COLOR=black><FONT SIZE=3>
Python raises one: it prints a traceback and an error message.
</FONT></FONT><A NAME="@default950"></A></P><P><FONT COLOR=black><FONT SIZE=3>The </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>raise</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> statement takes a detailed error message as an
 
optional argument. For example:</FONT></FONT></P><PRE CLASS="verbatim"><FONT COLOR=blue><FONT SIZE=4>&gt;&gt;&gt; raise ValueError, 'value does not appear in the dictionary'
 
 
 
 
The <TT>raise</TT> statement takes a detailed error message as an
optional argument. For example:
<PRE CLASS="verbatim">&gt;&gt;&gt; raise ValueError, 'value does not appear in the dictionary'
Traceback (most recent call last):
Traceback (most recent call last):
   File "&lt;stdin&gt;", line 1, in ?
   File "&lt;stdin&gt;", line 1, in ?
ValueError: value does not appear in the dictionary
ValueError: value does not appear in the dictionary
</FONT></FONT></PRE><P><FONT COLOR=black><FONT SIZE=3>A reverse lookup is much slower than a forward lookup; if you
</PRE>
A reverse lookup is much slower than a forward lookup; if you
have to do it often, or if the dictionary gets big, the performance
have to do it often, or if the dictionary gets big, the performance
of your program will suffer.</FONT></FONT></P><DIV CLASS="theorem"><FONT COLOR=black><FONT SIZE=3><B>Exercise&#XA0;4</B></FONT></FONT><FONT COLOR=black><FONT SIZE=3>&#XA0;&#XA0;<EM>
of your program will suffer.
Modify </EM></FONT></FONT><CODE><FONT COLOR=black><FONT SIZE=3><EM>reverse_lookup</EM></FONT></FONT></CODE><FONT COLOR=black><FONT SIZE=3><EM> so that it builds and returns a list
<DIV CLASS="theorem">'''Exercise&#XA0;4'''&#XA0;&#XA0;''
of </EM></FONT></FONT><FONT COLOR=black><FONT SIZE=3>all</FONT></FONT><FONT COLOR=black><FONT SIZE=3><EM> keys that map to </EM></FONT></FONT><FONT COLOR=black><FONT SIZE=3><EM><TT>v</TT></EM></FONT></FONT><FONT COLOR=black><FONT SIZE=3><EM>, or an empty list if there
Modify ''<CODE>''reverse_lookup''</CODE>'' so that it builds and returns a list
of ''all'' keys that map to ''''<TT>v</TT>'''', or an empty list if there
are none.
are none.
</EM></FONT></FONT></DIV><H2 CLASS="section"><A NAME="toc123"></A><A NAME="htoc136"><FONT COLOR=black><FONT SIZE=3>11.4</FONT></FONT></A><FONT COLOR=black><FONT SIZE=3>&#XA0;&#XA0;Dictionaries and lists</FONT></FONT></H2><P><FONT COLOR=black><FONT SIZE=3>Lists can appear as values in a dictionary. For example, if you
''</DIV>=== 11.4&#XA0;&#XA0;Dictionaries and lists ===
 
Lists can appear as values in a dictionary. For example, if you
were given a dictionary that maps from letters to frequencies, you
were given a dictionary that maps from letters to frequencies, you
might want to invert it; that is, create a dictionary that maps
might want to invert it; that is, create a dictionary that maps
from frequencies to letters. Since there might be several letters
from frequencies to letters. Since there might be several letters
with the same frequency, each value in the inverted dictionary
with the same frequency, each value in the inverted dictionary
should be a list of letters.</FONT></FONT></P><P><A NAME="@default951"></A><FONT COLOR=black><FONT SIZE=3>
should be a list of letters.
</FONT></FONT><A NAME="@default952"></A></P><P><FONT COLOR=black><FONT SIZE=3>Here is a function that inverts a dictionary:</FONT></FONT></P><PRE CLASS="verbatim"><FONT COLOR=blue><FONT SIZE=4>def invert_dict(d):
 
 
 
 
Here is a function that inverts a dictionary:
<PRE CLASS="verbatim">def invert_dict(d):
     inv = dict()
     inv = dict()
     for key in d:
     for key in d:
Line 218: Line 343:
             inv[val].append(key)
             inv[val].append(key)
     return inv
     return inv
</FONT></FONT></PRE><P><FONT COLOR=black><FONT SIZE=3>Each time through the loop, </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>key</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> gets a key from </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>d</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> and  
</PRE>
</FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>val</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> gets the corresponding value. If </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>val</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> is not in </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>inv</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3>,
Each time through the loop, <TT>key</TT> gets a key from <TT>d</TT> and  
<TT>val</TT> gets the corresponding value. If <TT>val</TT> is not in <TT>inv</TT>,
that means we haven&#X2019;t seen it before, so we create a new item and
that means we haven&#X2019;t seen it before, so we create a new item and
initialize it with a </FONT></FONT><FONT COLOR=black><FONT SIZE=3><B>singleton</B></FONT></FONT><FONT COLOR=black><FONT SIZE=3> (a list that contains a
initialize it with a '''singleton''' (a list that contains a
single element). Otherwise we have seen this value before, so we
single element). Otherwise we have seen this value before, so we
append the corresponding key to the list.</FONT></FONT></P><P><A NAME="@default953"></A></P><P><FONT COLOR=black><FONT SIZE=3>Here is an example:</FONT></FONT></P><PRE CLASS="verbatim"><FONT COLOR=blue><FONT SIZE=4>&gt;&gt;&gt; hist = histogram('parrot')
append the corresponding key to the list.
 
Here is an example:
<PRE CLASS="verbatim">&gt;&gt;&gt; hist = histogram('parrot')
&gt;&gt;&gt; print hist
&gt;&gt;&gt; print hist
{'a': 1, 'p': 1, 'r': 2, 't': 1, 'o': 1}
{'a': 1, 'p': 1, 'r': 2, 't': 1, 'o': 1}
Line 229: Line 358:
&gt;&gt;&gt; print inv
&gt;&gt;&gt; print inv
{1: ['a', 'p', 't', 'o'], 2: ['r']}
{1: ['a', 'p', 't', 'o'], 2: ['r']}
</FONT></FONT></PRE><P><FONT COLOR=black><FONT SIZE=3>And here is a diagram showing </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>hist</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> and </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>inv</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3>:</FONT></FONT></P><P><A NAME="@default954"></A><FONT COLOR=black><FONT SIZE=3>
</PRE>
</FONT></FONT><A NAME="@default955"></A></P><DIV CLASS="center"><FONT COLOR=black><FONT SIZE=3><IMG SRC="book018.png"></FONT></FONT></DIV><P><FONT COLOR=black><FONT SIZE=3>A dictionary is represented as a box with the type </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>dict</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> above it
And here is a diagram showing <TT>hist</TT> and <TT>inv</TT>:
 
 
 
<DIV CLASS="center"><IMG SRC="book018.png"></DIV>
A dictionary is represented as a box with the type <TT>dict</TT> above it
and the key-value pairs inside. If the values are integers, floats or
and the key-value pairs inside. If the values are integers, floats or
strings, I usually draw them inside the box, but I usually draw lists
strings, I usually draw them inside the box, but I usually draw lists
outside the box, just to keep the diagram simple.</FONT></FONT></P><P><FONT COLOR=black><FONT SIZE=3>Lists can be values in a dictionary, as this example shows, but they
outside the box, just to keep the diagram simple.
cannot be keys. Here&#X2019;s what happens if you try:</FONT></FONT></P><P><A NAME="@default956"></A><FONT COLOR=black><FONT SIZE=3>
 
</FONT></FONT><A NAME="@default957"></A></P><PRE CLASS="verbatim"><FONT COLOR=blue><FONT SIZE=4>&gt;&gt;&gt; t = [1, 2, 3]
Lists can be values in a dictionary, as this example shows, but they
cannot be keys. Here&#X2019;s what happens if you try:
 
 
 
<PRE CLASS="verbatim">&gt;&gt;&gt; t = [1, 2, 3]
&gt;&gt;&gt; d = dict()
&gt;&gt;&gt; d = dict()
&gt;&gt;&gt; d[t] = 'oops'
&gt;&gt;&gt; d[t] = 'oops'
Line 241: Line 380:
   File "&lt;stdin&gt;", line 1, in ?
   File "&lt;stdin&gt;", line 1, in ?
TypeError: list objects are unhashable
TypeError: list objects are unhashable
</FONT></FONT></PRE><P><FONT COLOR=black><FONT SIZE=3>I mentioned earlier that a dictionary is implemented using
</PRE>
a hashtable and that means that the keys have to be </FONT></FONT><FONT COLOR=black><FONT SIZE=3><B>hashable</B></FONT></FONT><FONT COLOR=black><FONT SIZE=3>.</FONT></FONT></P><P><A NAME="@default958"></A><FONT COLOR=black><FONT SIZE=3>
I mentioned earlier that a dictionary is implemented using
</FONT></FONT><A NAME="@default959"></A></P><P><FONT COLOR=black><FONT SIZE=3>A </FONT></FONT><FONT COLOR=black><FONT SIZE=3><B>hash</B></FONT></FONT><FONT COLOR=black><FONT SIZE=3> is a function that takes a value (of any kind)
a hashtable and that means that the keys have to be '''hashable'''.
 
 
 
 
A '''hash''' is a function that takes a value (of any kind)
and returns an integer. Dictionaries use these integers,
and returns an integer. Dictionaries use these integers,
called hash values, to store and look up key-value pairs.</FONT></FONT></P><P><A NAME="@default960"></A></P><P><FONT COLOR=black><FONT SIZE=3>This system works fine if the keys are immutable. But if the
called hash values, to store and look up key-value pairs.
 
This system works fine if the keys are immutable. But if the
keys are mutable, like lists, bad things happen. For example,
keys are mutable, like lists, bad things happen. For example,
when you create a key-value pair, Python hashes the key and  
when you create a key-value pair, Python hashes the key and  
Line 252: Line 398:
In that case you might have two entries for the same key,
In that case you might have two entries for the same key,
or you might not be able to find a key. Either way, the
or you might not be able to find a key. Either way, the
dictionary wouldn&#X2019;t work correctly.</FONT></FONT></P><P><FONT COLOR=black><FONT SIZE=3>That&#X2019;s why the keys have to be hashable, and why mutable types like
dictionary wouldn&#X2019;t work correctly.
 
That&#X2019;s why the keys have to be hashable, and why mutable types like
lists aren&#X2019;t. The simplest way to get around this limitation is to
lists aren&#X2019;t. The simplest way to get around this limitation is to
use tuples, which we will see in the next chapter.</FONT></FONT></P><P><FONT COLOR=black><FONT SIZE=3>Since dictionaries are mutable, they can&#X2019;t be used as keys,
use tuples, which we will see in the next chapter.
but they </FONT></FONT><FONT COLOR=black><FONT SIZE=3><EM>can</EM></FONT></FONT><FONT COLOR=black><FONT SIZE=3> be used as values.</FONT></FONT></P><DIV CLASS="theorem"><FONT COLOR=black><FONT SIZE=3><B>Exercise&#XA0;5</B></FONT></FONT><FONT COLOR=black><FONT SIZE=3>&#XA0;&#XA0;<EM>
 
Read the documentation of the dictionary method </EM></FONT></FONT><FONT COLOR=black><FONT SIZE=3><EM><TT>setdefault</TT></EM></FONT></FONT><FONT COLOR=black><FONT SIZE=3><EM>
Since dictionaries are mutable, they can&#X2019;t be used as keys,
and use it to write a more concise version of </EM></FONT></FONT><CODE><FONT COLOR=black><FONT SIZE=3><EM>invert_dict</EM></FONT></FONT></CODE><FONT COLOR=black><FONT SIZE=3><EM>.</EM></FONT></FONT><P><A NAME="@default961"></A><FONT COLOR=black><FONT SIZE=3><EM>
but they ''can'' be used as values.
</EM></FONT></FONT><A NAME="@default962"></A></P></DIV><H2 CLASS="section"><A NAME="toc124"></A><A NAME="htoc137"><FONT COLOR=black><FONT SIZE=3>11.5</FONT></FONT></A><FONT COLOR=black><FONT SIZE=3>&#XA0;&#XA0;Memos</FONT></FONT></H2><P><FONT COLOR=black><FONT SIZE=3>If you played with the </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>fibonacci</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> function from
<DIV CLASS="theorem">'''Exercise&#XA0;5'''&#XA0;&#XA0;''
Section&#XA0;</FONT></FONT><A HREF="book007.html#one more example"><FONT COLOR=black><FONT SIZE=3>6.7</FONT></FONT></A><FONT COLOR=black><FONT SIZE=3>, you might have noticed that the bigger
Read the documentation of the dictionary method ''''<TT>setdefault</TT>''''
and use it to write a more concise version of ''<CODE>''invert_dict''</CODE>''.''
''
''
</DIV>=== 11.5&#XA0;&#XA0;Memos ===
 
If you played with the <TT>fibonacci</TT> function from
Section&#XA0;6.7, you might have noticed that the bigger
the argument you provide, the longer the function takes to run.
the argument you provide, the longer the function takes to run.
Furthermore, the run time increases very quickly.</FONT></FONT></P><P><A NAME="@default963"></A><FONT COLOR=black><FONT SIZE=3>
Furthermore, the run time increases very quickly.
</FONT></FONT><A NAME="@default964"></A></P><P><FONT COLOR=black><FONT SIZE=3>To understand why, consider this </FONT></FONT><FONT COLOR=black><FONT SIZE=3><B>call graph</B></FONT></FONT><FONT COLOR=black><FONT SIZE=3> for
 
</FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>fibonacci</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> with </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>n=4</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3>:</FONT></FONT></P><DIV CLASS="center"><FONT COLOR=black><FONT SIZE=3><IMG SRC="book019.png"></FONT></FONT></DIV><P><FONT COLOR=black><FONT SIZE=3>A call graph shows a set of function frames, with lines connecting each
 
 
 
To understand why, consider this '''call graph''' for
<TT>fibonacci</TT> with <TT>n=4</TT>:
<DIV CLASS="center"><IMG SRC="book019.png"></DIV>
A call graph shows a set of function frames, with lines connecting each
frame to the frames of the functions it calls. At the top of the
frame to the frames of the functions it calls. At the top of the
graph, </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>fibonacci</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> with </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>n=4</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> calls </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>fibonacci</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> with </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>n=3</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> and </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>n=2</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3>. In turn, </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>fibonacci</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> with </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>n=3</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> calls
graph, <TT>fibonacci</TT> with <TT>n=4</TT> calls <TT>fibonacci</TT> with <TT>n=3</TT> and <TT>n=2</TT>. In turn, <TT>fibonacci</TT> with <TT>n=3</TT> calls
</FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>fibonacci</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> with </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>n=2</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> and </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>n=1</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3>. And so on.</FONT></FONT></P><P><A NAME="@default965"></A><FONT COLOR=black><FONT SIZE=3>
<TT>fibonacci</TT> with <TT>n=2</TT> and <TT>n=1</TT>. And so on.
</FONT></FONT><A NAME="@default966"></A><FONT COLOR=black><FONT SIZE=3>
 
</FONT></FONT><A NAME="@default967"></A></P><P><FONT COLOR=black><FONT SIZE=3>Count how many times </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>fibonacci(0)</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> and </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>fibonacci(1)</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> are
 
 
 
 
Count how many times <TT>fibonacci(0)</TT> and <TT>fibonacci(1)</TT> are
called. This is an inefficient solution to the problem, and it gets
called. This is an inefficient solution to the problem, and it gets
worse as the argument gets bigger.</FONT></FONT></P><P><A NAME="@default968"></A></P><P><FONT COLOR=black><FONT SIZE=3>One solution is to keep track of values that have already been
worse as the argument gets bigger.
 
One solution is to keep track of values that have already been
computed by storing them in a dictionary. A previously computed value
computed by storing them in a dictionary. A previously computed value
that is stored for later use is called a </FONT></FONT><FONT COLOR=black><FONT SIZE=3><B>memo</B></FONT></FONT><SUP><A NAME="text21" HREF="#note21"><FONT COLOR=black><FONT SIZE=3>1</FONT></FONT></A></SUP><FONT COLOR=black><FONT SIZE=3>. Here is an
that is stored for later use is called a '''memo'''<SUP>1</SUP>. Here is an
implementation of </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>fibonacci</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> using memos:</FONT></FONT></P><PRE CLASS="verbatim"><FONT COLOR=blue><FONT SIZE=4>known = {0:0, 1:1}
implementation of <TT>fibonacci</TT> using memos:
<PRE CLASS="verbatim">known = {0:0, 1:1}


def fibonacci(n):
def fibonacci(n):
Line 282: Line 450:
     known[n] = res
     known[n] = res
     return res
     return res
</FONT></FONT></PRE><P><FONT COLOR=black><FONT SIZE=3><TT>known</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> is a dictionary that keeps track of the Fibonacci
</PRE>
<TT>known</TT> is a dictionary that keeps track of the Fibonacci
numbers we already know. It starts with
numbers we already know. It starts with
two items: 0 maps to 0 and 1 maps to 1.</FONT></FONT></P><P><FONT COLOR=black><FONT SIZE=3>Whenever </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>fibonacci</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> is called, it checks </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>known</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3>.
two items: 0 maps to 0 and 1 maps to 1.
 
Whenever <TT>fibonacci</TT> is called, it checks <TT>known</TT>.
If the result is already there, it can return
If the result is already there, it can return
immediately. Otherwise it has to  
immediately. Otherwise it has to  
compute the new value, add it to the dictionary, and return it.</FONT></FONT></P><DIV CLASS="theorem"><FONT COLOR=black><FONT SIZE=3><B>Exercise&#XA0;6</B></FONT></FONT><FONT COLOR=black><FONT SIZE=3>&#XA0;&#XA0;<EM>
compute the new value, add it to the dictionary, and return it.
Run this version of </EM></FONT></FONT><FONT COLOR=black><FONT SIZE=3><EM><TT>fibonacci</TT></EM></FONT></FONT><FONT COLOR=black><FONT SIZE=3><EM> and the original with
<DIV CLASS="theorem">'''Exercise&#XA0;6'''&#XA0;&#XA0;''
Run this version of ''''<TT>fibonacci</TT>'''' and the original with
a range of parameters and compare their run times.
a range of parameters and compare their run times.
</EM></FONT></FONT></DIV><H2 CLASS="section"><A NAME="toc125"></A><A NAME="htoc138"><FONT COLOR=black><FONT SIZE=3>11.6</FONT></FONT></A><FONT COLOR=black><FONT SIZE=3>&#XA0;&#XA0;Global variables</FONT></FONT></H2><P><A NAME="@default969"></A><FONT COLOR=black><FONT SIZE=3>
''</DIV>=== 11.6&#XA0;&#XA0;Global variables ===
</FONT></FONT><A NAME="@default970"></A></P><P><FONT COLOR=black><FONT SIZE=3>In the previous example, </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>known</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> is created outside the function,
 
so it belongs to the special frame called </FONT></FONT><CODE><FONT COLOR=black><FONT SIZE=3>__main__</FONT></FONT></CODE><FONT COLOR=black><FONT SIZE=3>.
 
Variables in </FONT></FONT><CODE><FONT COLOR=black><FONT SIZE=3>__main__</FONT></FONT></CODE><FONT COLOR=black><FONT SIZE=3> are sometimes called </FONT></FONT><FONT COLOR=black><FONT SIZE=3><B>global</B></FONT></FONT><FONT COLOR=black><FONT SIZE=3>
 
 
In the previous example, <TT>known</TT> is created outside the function,
so it belongs to the special frame called <CODE>__main__</CODE>.
Variables in <CODE>__main__</CODE> are sometimes called '''global'''
because they can be accessed from any function. Unlike local
because they can be accessed from any function. Unlike local
variables, which disappear when their function ends, global variables
variables, which disappear when their function ends, global variables
persist from one function call to the next.</FONT></FONT></P><P><A NAME="@default971"></A></P><P><FONT COLOR=black><FONT SIZE=3>It is common to use global variables for </FONT></FONT><FONT COLOR=black><FONT SIZE=3><B>flags</B></FONT></FONT><FONT COLOR=black><FONT SIZE=3>; that is,  
persist from one function call to the next.
 
It is common to use global variables for '''flags'''; that is,  
boolean variables that indicate (&#X201C;flag&#X201D;) whether a condition
boolean variables that indicate (&#X201C;flag&#X201D;) whether a condition
is true. For example, some programs use
is true. For example, some programs use
a flag named </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>verbose</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> to control the level of detail in the
a flag named <TT>verbose</TT> to control the level of detail in the
output:</FONT></FONT></P><PRE CLASS="verbatim"><FONT COLOR=blue><FONT SIZE=4>verbose = True
output:
<PRE CLASS="verbatim">verbose = True


def example1():
def example1():
     if verbose:
     if verbose:
         print 'Running example1'
         print 'Running example1'
</FONT></FONT></PRE><P><FONT COLOR=black><FONT SIZE=3>If you try to reassign a global variable, you might be surprised.
</PRE>
If you try to reassign a global variable, you might be surprised.
The following example is supposed to keep track of whether the
The following example is supposed to keep track of whether the
function has been called:</FONT></FONT></P><P><A NAME="@default972"></A><FONT COLOR=black><FONT SIZE=3>
function has been called:
</FONT></FONT><A NAME="@default973"></A></P><PRE CLASS="verbatim"><FONT COLOR=blue><FONT SIZE=4>been_called = False
 
 
 
<PRE CLASS="verbatim">been_called = False


def example2():
def example2():
     been_called = True        # WRONG
     been_called = True        # WRONG
</FONT></FONT></PRE><P><FONT COLOR=black><FONT SIZE=3>But if you run it you will see that the value of </FONT></FONT><CODE><FONT COLOR=black><FONT SIZE=3>been_called</FONT></FONT></CODE><FONT COLOR=black><FONT SIZE=3>
</PRE>
doesn&#X2019;t change. The problem is that </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>example2</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> creates a new local
But if you run it you will see that the value of <CODE>been_called</CODE>
variable named </FONT></FONT><CODE><FONT COLOR=black><FONT SIZE=3>been_called</FONT></FONT></CODE><FONT COLOR=black><FONT SIZE=3>. The local variable goes away when
doesn&#X2019;t change. The problem is that <TT>example2</TT> creates a new local
the function ends, and has no effect on the global variable.</FONT></FONT></P><P><A NAME="@default974"></A><FONT COLOR=black><FONT SIZE=3>
variable named <CODE>been_called</CODE>. The local variable goes away when
</FONT></FONT><A NAME="@default975"></A><FONT COLOR=black><FONT SIZE=3>
the function ends, and has no effect on the global variable.
</FONT></FONT><A NAME="@default976"></A></P><P><FONT COLOR=black><FONT SIZE=3>To reassign a global variable inside a function you have to
 
</FONT></FONT><FONT COLOR=black><FONT SIZE=3><B>declare</B></FONT></FONT><FONT COLOR=black><FONT SIZE=3> the global variable before you use it:</FONT></FONT></P><PRE CLASS="verbatim"><FONT COLOR=blue><FONT SIZE=4>been_called = False
 
 
 
 
To reassign a global variable inside a function you have to
'''declare''' the global variable before you use it:
<PRE CLASS="verbatim">been_called = False


def example2():
def example2():
     global been_called  
     global been_called  
     been_called = True
     been_called = True
</FONT></FONT></PRE><P><FONT COLOR=black><FONT SIZE=3>The </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>global</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> statement tells the interpreter
</PRE>
something like, &#X201C;In this function, when I say </FONT></FONT><CODE><FONT COLOR=black><FONT SIZE=3>been_called</FONT></FONT></CODE><FONT COLOR=black><FONT SIZE=3>, I
The <TT>global</TT> statement tells the interpreter
mean the global variable; don&#X2019;t create a local one.&#X201D;</FONT></FONT></P><P><A NAME="@default977"></A><FONT COLOR=black><FONT SIZE=3>
something like, &#X201C;In this function, when I say <CODE>been_called</CODE>, I
</FONT></FONT><A NAME="@default978"></A></P><P><FONT COLOR=black><FONT SIZE=3>Here&#X2019;s an example that tries to update a global variable:</FONT></FONT></P><PRE CLASS="verbatim"><FONT COLOR=blue><FONT SIZE=4>count = 0
mean the global variable; don&#X2019;t create a local one.&#X201D;
 
 
 
 
Here&#X2019;s an example that tries to update a global variable:
<PRE CLASS="verbatim">count = 0


def example3():
def example3():
     count = count + 1          # WRONG
     count = count + 1          # WRONG
</FONT></FONT></PRE><P><FONT COLOR=black><FONT SIZE=3>If you run it you get:</FONT></FONT></P><P><A NAME="@default979"></A><FONT COLOR=black><FONT SIZE=3>
</PRE>
</FONT></FONT><A NAME="@default980"></A></P><PRE CLASS="verbatim"><FONT COLOR=blue><FONT SIZE=4>UnboundLocalError: local variable 'count' referenced before assignment
If you run it you get:
</FONT></FONT></PRE><P><FONT COLOR=black><FONT SIZE=3>Python assumes that </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>count</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> is local, which means
 
 
 
<PRE CLASS="verbatim">UnboundLocalError: local variable 'count' referenced before assignment
</PRE>
Python assumes that <TT>count</TT> is local, which means
that you are reading it before writing it. The solution, again,
that you are reading it before writing it. The solution, again,
is to declare </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>count</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> global.</FONT></FONT></P><P><A NAME="@default981"></A></P><PRE CLASS="verbatim"><FONT COLOR=blue><FONT SIZE=4>def example3():
is to declare <TT>count</TT> global.
 
<PRE CLASS="verbatim">def example3():
     global count
     global count
     count += 1
     count += 1
</FONT></FONT></PRE><P><FONT COLOR=black><FONT SIZE=3>If the global value is mutable, you can modify it without
</PRE>
declaring it:</FONT></FONT></P><P><A NAME="@default982"></A></P><PRE CLASS="verbatim"><FONT COLOR=blue><FONT SIZE=4>known = {0:0, 1:1}
If the global value is mutable, you can modify it without
declaring it:
 
<PRE CLASS="verbatim">known = {0:0, 1:1}


def example4():
def example4():
     known[2] = 1
     known[2] = 1
</FONT></FONT></PRE><P><FONT COLOR=black><FONT SIZE=3>So you can add, remove and replace elements of a global list or
</PRE>
So you can add, remove and replace elements of a global list or
dictionary, but if you want to reassign the variable, you
dictionary, but if you want to reassign the variable, you
have to declare it:</FONT></FONT></P><PRE CLASS="verbatim"><FONT COLOR=blue><FONT SIZE=4>def example5():
have to declare it:
<PRE CLASS="verbatim">def example5():
     global known
     global known
     known = dict()
     known = dict()
</FONT></FONT></PRE><H2 CLASS="section"><A NAME="toc126"></A><A NAME="htoc139"><FONT COLOR=black><FONT SIZE=3>11.7</FONT></FONT></A><FONT COLOR=black><FONT SIZE=3>&#XA0;&#XA0;Long integers</FONT></FONT></H2><P><A NAME="@default983"></A><FONT COLOR=black><FONT SIZE=3>
</PRE>=== 11.7&#XA0;&#XA0;Long integers ===
</FONT></FONT><A NAME="@default984"></A><FONT COLOR=black><FONT SIZE=3>
 
</FONT></FONT><A NAME="@default985"></A></P><P><FONT COLOR=black><FONT SIZE=3>If you compute </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>fibonacci(50)</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3>, you get:</FONT></FONT></P><PRE CLASS="verbatim"><FONT COLOR=blue><FONT SIZE=4>&gt;&gt;&gt; fibonacci(50)
 
 
 
 
If you compute <TT>fibonacci(50)</TT>, you get:
<PRE CLASS="verbatim">&gt;&gt;&gt; fibonacci(50)
12586269025L
12586269025L
</FONT></FONT></PRE><P><FONT COLOR=black><FONT SIZE=3>The </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>L</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> at the end indicates that the result is a long
</PRE>
integer</FONT></FONT><SUP><A NAME="text22" HREF="#note22"><FONT COLOR=black><FONT SIZE=3>2</FONT></FONT></A></SUP><FONT COLOR=black><FONT SIZE=3>, or type </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>long</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3>.</FONT></FONT></P><P><A NAME="@default986"></A></P><P><FONT COLOR=black><FONT SIZE=3>Values with type </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>int</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> have a limited range;
The <TT>L</TT> at the end indicates that the result is a long
integer<SUP>2</SUP>, or type <TT>long</TT>.
 
Values with type <TT>int</TT> have a limited range;
long integers can be arbitrarily big, but as they get bigger
long integers can be arbitrarily big, but as they get bigger
they consume more space and time.</FONT></FONT></P><P><FONT COLOR=black><FONT SIZE=3>The mathematical operators work on long integers, and the functions
they consume more space and time.
in the </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>math</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> module, too, so in general any code that
 
works with </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>int</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> will also work with </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>long</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3>.</FONT></FONT></P><P><FONT COLOR=black><FONT SIZE=3>Any time the result of a computation is too big to be represented with
The mathematical operators work on long integers, and the functions
an integer, Python converts the result as a long integer:</FONT></FONT></P><PRE CLASS="verbatim"><FONT COLOR=blue><FONT SIZE=4>&gt;&gt;&gt; 1000 * 1000
in the <TT>math</TT> module, too, so in general any code that
works with <TT>int</TT> will also work with <TT>long</TT>.
 
Any time the result of a computation is too big to be represented with
an integer, Python converts the result as a long integer:
<PRE CLASS="verbatim">&gt;&gt;&gt; 1000 * 1000
1000000
1000000
&gt;&gt;&gt; 100000 * 100000
&gt;&gt;&gt; 100000 * 100000
10000000000L
10000000000L
</FONT></FONT></PRE><P><FONT COLOR=black><FONT SIZE=3>In the first case the result has type </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>int</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3>; in the
</PRE>
second case it is </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>long</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3>.</FONT></FONT></P><DIV CLASS="theorem"><FONT COLOR=black><FONT SIZE=3><B>Exercise&#XA0;7</B></FONT></FONT><FONT COLOR=black><FONT SIZE=3>&#XA0;&#XA0;</FONT></FONT><P><A NAME="@default987"></A><FONT COLOR=black><FONT SIZE=3><EM>
In the first case the result has type <TT>int</TT>; in the
</EM></FONT></FONT><A NAME="@default988"></A><FONT COLOR=black><FONT SIZE=3><EM>
second case it is <TT>long</TT>.
</EM></FONT></FONT><A NAME="@default989"></A></P><P><FONT COLOR=black><FONT SIZE=3><EM>Exponentiation of large integers is the basis of common
<DIV CLASS="theorem">'''Exercise&#XA0;7'''&#XA0;&#XA0;
''
''''
''
 
''Exponentiation of large integers is the basis of common
algorithms for public-key encryption. Read the Wikipedia
algorithms for public-key encryption. Read the Wikipedia
page on the RSA algorithm</EM></FONT></FONT><SUP><A NAME="text23" HREF="#note23"><FONT COLOR=black><FONT SIZE=3><EM>3</EM></FONT></FONT></A></SUP><FONT COLOR=black><FONT SIZE=3><EM>
page on the RSA algorithm''<SUP>''3''</SUP>''
and write functions to encode and decode messages.</EM></FONT></FONT></P></DIV><H2 CLASS="section"><A NAME="toc127"></A><A NAME="htoc140"><FONT COLOR=black><FONT SIZE=3>11.8</FONT></FONT></A><FONT COLOR=black><FONT SIZE=3>&#XA0;&#XA0;Debugging</FONT></FONT></H2><P><FONT COLOR=black><FONT SIZE=3>
and write functions to encode and decode messages.''
</FONT></FONT><A NAME="@default990"></A></P><P><FONT COLOR=black><FONT SIZE=3>As you work with bigger datasets it can become unwieldy to
</DIV>=== 11.8&#XA0;&#XA0;Debugging ===
 
 
 
 
As you work with bigger datasets it can become unwieldy to
debug by printing and checking data by hand. Here are some
debug by printing and checking data by hand. Here are some
suggestions for debugging large datasets:</FONT></FONT></P><DL CLASS="description"><DT CLASS="dt-description"><FONT COLOR=black><FONT SIZE=3><B>Scale down the input:</B></FONT></FONT></DT><DD CLASS="dd-description"><FONT COLOR=black><FONT SIZE=3> If possible, reduce the size of the
suggestions for debugging large datasets:
<DL CLASS="description"><DT CLASS="dt-description">'''Scale down the input:'''</DT><DD CLASS="dd-description"> If possible, reduce the size of the
dataset. For example if the program reads a text file, start with
dataset. For example if the program reads a text file, start with
just the first 10 lines, or with the smallest example you can find.
just the first 10 lines, or with the smallest example you can find.
You can either edit the files themselves, or (better) modify the
You can either edit the files themselves, or (better) modify the
program so it reads only the first </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>n</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> lines.</FONT></FONT><P><FONT COLOR=black><FONT SIZE=3>If there is an error, you can reduce </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>n</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> to the smallest
program so it reads only the first <TT>n</TT> lines.
If there is an error, you can reduce <TT>n</TT> to the smallest
value that manifests the error, and then increase it gradually
value that manifests the error, and then increase it gradually
as you find and correct errors.</FONT></FONT></P></DD><DT CLASS="dt-description"><FONT COLOR=black><FONT SIZE=3><B>Check summaries and types:</B></FONT></FONT></DT><DD CLASS="dd-description"><FONT COLOR=black><FONT SIZE=3> Instead of printing and checking the
as you find and correct errors.
</DD><DT CLASS="dt-description">'''Check summaries and types:'''</DT><DD CLASS="dd-description"> Instead of printing and checking the
entire dataset, consider printing summaries of the data: for example,
entire dataset, consider printing summaries of the data: for example,
the number of items in a dictionary or the total of a list of numbers.</FONT></FONT><P><FONT COLOR=black><FONT SIZE=3>A common cause of runtime errors is a value that is not the right
the number of items in a dictionary or the total of a list of numbers.
A common cause of runtime errors is a value that is not the right
type. For debugging this kind of error, it is often enough to print
type. For debugging this kind of error, it is often enough to print
the type of a value.</FONT></FONT></P></DD><DT CLASS="dt-description"><FONT COLOR=black><FONT SIZE=3><B>Write self-checks:</B></FONT></FONT></DT><DD CLASS="dd-description"><FONT COLOR=black><FONT SIZE=3> Sometimes you can write code to check
the type of a value.
</DD><DT CLASS="dt-description">'''Write self-checks:'''</DT><DD CLASS="dd-description"> Sometimes you can write code to check
for errors automatically. For example, if you are computing the
for errors automatically. For example, if you are computing the
average of a list of numbers, you could check that the result is
average of a list of numbers, you could check that the result is
not greater than the largest element in the list or less than
not greater than the largest element in the list or less than
the smallest. This is called a &#X201C;sanity check&#X201D; because it detects
the smallest. This is called a &#X201C;sanity check&#X201D; because it detects
results that are &#X201C;insane.&#X201D;</FONT></FONT><P><A NAME="@default991"></A><FONT COLOR=black><FONT SIZE=3>
results that are &#X201C;insane.&#X201D;
</FONT></FONT><A NAME="@default992"></A></P><P><FONT COLOR=black><FONT SIZE=3>Another kind of check compares the results of two different
 
 
 
Another kind of check compares the results of two different
computations to see if they are consistent. This is called a
computations to see if they are consistent. This is called a
&#X201C;consistency check.&#X201D;</FONT></FONT></P></DD><DT CLASS="dt-description"><FONT COLOR=black><FONT SIZE=3><B>Pretty print the output:</B></FONT></FONT></DT><DD CLASS="dd-description"><FONT COLOR=black><FONT SIZE=3> Formatting debugging output
&#X201C;consistency check.&#X201D;
</DD><DT CLASS="dt-description">'''Pretty print the output:'''</DT><DD CLASS="dd-description"> Formatting debugging output
can make it easier to spot an error. We saw an example in
can make it easier to spot an error. We saw an example in
Section&#XA0;</FONT></FONT><A HREF="book007.html#factdebug"><FONT COLOR=black><FONT SIZE=3>6.9</FONT></FONT></A><FONT COLOR=black><FONT SIZE=3>. The </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>pprint</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> module provides
Section&#XA0;6.9. The <TT>pprint</TT> module provides
a </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>pprint</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> function that displays built-in types in
a <TT>pprint</TT> function that displays built-in types in
a more human-readable format.</FONT></FONT><P><A NAME="@default993"></A><FONT COLOR=black><FONT SIZE=3>
a more human-readable format.
</FONT></FONT><A NAME="@default994"></A><FONT COLOR=black><FONT SIZE=3>
 
</FONT></FONT><A NAME="@default995"></A></P></DD></DL><P><FONT COLOR=black><FONT SIZE=3>Again, time you spend building scaffolding can reduce
 
the time you spend debugging.</FONT></FONT></P><P><A NAME="@default996"></A></P><H2 CLASS="section"><A NAME="toc128"></A><A NAME="htoc141"><FONT COLOR=black><FONT SIZE=3>11.9</FONT></FONT></A><FONT COLOR=black><FONT SIZE=3>&#XA0;&#XA0;Glossary</FONT></FONT></H2><DL CLASS="description"><DT CLASS="dt-description"><FONT COLOR=black><FONT SIZE=3><B>dictionary:</B></FONT></FONT></DT><DD CLASS="dd-description"><FONT COLOR=black><FONT SIZE=3> A mapping from a set of keys to their
 
</DD></DL>
Again, time you spend building scaffolding can reduce
the time you spend debugging.
 
=== 11.9&#XA0;&#XA0;Glossary ===
 
<DL CLASS="description"><DT CLASS="dt-description">'''dictionary:'''</DT><DD CLASS="dd-description"> A mapping from a set of keys to their
corresponding values.
corresponding values.
</FONT></FONT><A NAME="@default997"></A></DD><DT CLASS="dt-description"><FONT COLOR=black><FONT SIZE=3><B>key-value pair:</B></FONT></FONT></DT><DD CLASS="dd-description"><FONT COLOR=black><FONT SIZE=3> The representation of the mapping from
</DD><DT CLASS="dt-description">'''key-value pair:'''</DT><DD CLASS="dd-description"> The representation of the mapping from
a key to a value.
a key to a value.
</FONT></FONT><A NAME="@default998"></A></DD><DT CLASS="dt-description"><FONT COLOR=black><FONT SIZE=3><B>item:</B></FONT></FONT></DT><DD CLASS="dd-description"><FONT COLOR=black><FONT SIZE=3> Another name for a key-value pair.
</DD><DT CLASS="dt-description">'''item:'''</DT><DD CLASS="dd-description"> Another name for a key-value pair.
</FONT></FONT><A NAME="@default999"></A></DD><DT CLASS="dt-description"><FONT COLOR=black><FONT SIZE=3><B>key:</B></FONT></FONT></DT><DD CLASS="dd-description"><FONT COLOR=black><FONT SIZE=3> An object that appears in a dictionary as the
</DD><DT CLASS="dt-description">'''key:'''</DT><DD CLASS="dd-description"> An object that appears in a dictionary as the
first part of a key-value pair.
first part of a key-value pair.
</FONT></FONT><A NAME="@default1000"></A></DD><DT CLASS="dt-description"><FONT COLOR=black><FONT SIZE=3><B>value:</B></FONT></FONT></DT><DD CLASS="dd-description"><FONT COLOR=black><FONT SIZE=3> An object that appears in a dictionary as the
</DD><DT CLASS="dt-description">'''value:'''</DT><DD CLASS="dd-description"> An object that appears in a dictionary as the
second part of a key-value pair. This is more specific than
second part of a key-value pair. This is more specific than
our previous use of the word &#X201C;value.&#X201D;
our previous use of the word &#X201C;value.&#X201D;
</FONT></FONT><A NAME="@default1001"></A></DD><DT CLASS="dt-description"><FONT COLOR=black><FONT SIZE=3><B>implementation:</B></FONT></FONT></DT><DD CLASS="dd-description"><FONT COLOR=black><FONT SIZE=3> A way of performing a computation.
</DD><DT CLASS="dt-description">'''implementation:'''</DT><DD CLASS="dd-description"> A way of performing a computation.
</FONT></FONT><A NAME="@default1002"></A></DD><DT CLASS="dt-description"><FONT COLOR=black><FONT SIZE=3><B>hashtable:</B></FONT></FONT></DT><DD CLASS="dd-description"><FONT COLOR=black><FONT SIZE=3> The algorithm used to implement Python
</DD><DT CLASS="dt-description">'''hashtable:'''</DT><DD CLASS="dd-description"> The algorithm used to implement Python
dictionaries.
dictionaries.
</FONT></FONT><A NAME="@default1003"></A></DD><DT CLASS="dt-description"><FONT COLOR=black><FONT SIZE=3><B>hash function:</B></FONT></FONT></DT><DD CLASS="dd-description"><FONT COLOR=black><FONT SIZE=3> A function used by a hashtable to compute the
</DD><DT CLASS="dt-description">'''hash function:'''</DT><DD CLASS="dd-description"> A function used by a hashtable to compute the
location for a key.
location for a key.
</FONT></FONT><A NAME="@default1004"></A></DD><DT CLASS="dt-description"><FONT COLOR=black><FONT SIZE=3><B>hashable:</B></FONT></FONT></DT><DD CLASS="dd-description"><FONT COLOR=black><FONT SIZE=3> A type that has a hash function. Immutable
</DD><DT CLASS="dt-description">'''hashable:'''</DT><DD CLASS="dd-description"> A type that has a hash function. Immutable
types like integers,
types like integers,
floats and strings are hashable; mutable types like lists and
floats and strings are hashable; mutable types like lists and
dictionaries are not.
dictionaries are not.
</FONT></FONT><A NAME="@default1005"></A></DD><DT CLASS="dt-description"><FONT COLOR=black><FONT SIZE=3><B>lookup:</B></FONT></FONT></DT><DD CLASS="dd-description"><FONT COLOR=black><FONT SIZE=3> A dictionary operation that takes a key and finds
</DD><DT CLASS="dt-description">'''lookup:'''</DT><DD CLASS="dd-description"> A dictionary operation that takes a key and finds
the corresponding value.
the corresponding value.
</FONT></FONT><A NAME="@default1006"></A></DD><DT CLASS="dt-description"><FONT COLOR=black><FONT SIZE=3><B>reverse lookup:</B></FONT></FONT></DT><DD CLASS="dd-description"><FONT COLOR=black><FONT SIZE=3> A dictionary operation that takes a value and finds
</DD><DT CLASS="dt-description">'''reverse lookup:'''</DT><DD CLASS="dd-description"> A dictionary operation that takes a value and finds
one or more keys that map to it.
one or more keys that map to it.
</FONT></FONT><A NAME="@default1007"></A></DD><DT CLASS="dt-description"><FONT COLOR=black><FONT SIZE=3><B>singleton:</B></FONT></FONT></DT><DD CLASS="dd-description"><FONT COLOR=black><FONT SIZE=3> A list (or other sequence) with a single element.
</DD><DT CLASS="dt-description">'''singleton:'''</DT><DD CLASS="dd-description"> A list (or other sequence) with a single element.
</FONT></FONT><A NAME="@default1008"></A></DD><DT CLASS="dt-description"><FONT COLOR=black><FONT SIZE=3><B>call graph:</B></FONT></FONT></DT><DD CLASS="dd-description"><FONT COLOR=black><FONT SIZE=3> A diagram that shows every frame created during
</DD><DT CLASS="dt-description">'''call graph:'''</DT><DD CLASS="dd-description"> A diagram that shows every frame created during
the execution of a program, with an arrow from each caller to
the execution of a program, with an arrow from each caller to
each callee.  
each callee.  
</FONT></FONT><A NAME="@default1009"></A><FONT COLOR=black><FONT SIZE=3>
 
</FONT></FONT><A NAME="@default1010"></A></DD><DT CLASS="dt-description"><FONT COLOR=black><FONT SIZE=3><B>histogram:</B></FONT></FONT></DT><DD CLASS="dd-description"><FONT COLOR=black><FONT SIZE=3> A set of counters.
</DD><DT CLASS="dt-description">'''histogram:'''</DT><DD CLASS="dd-description"> A set of counters.
</FONT></FONT><A NAME="@default1011"></A></DD><DT CLASS="dt-description"><FONT COLOR=black><FONT SIZE=3><B>memo:</B></FONT></FONT></DT><DD CLASS="dd-description"><FONT COLOR=black><FONT SIZE=3> A computed value stored to avoid unnecessary future  
</DD><DT CLASS="dt-description">'''memo:'''</DT><DD CLASS="dd-description"> A computed value stored to avoid unnecessary future  
computation.
computation.
</FONT></FONT><A NAME="@default1012"></A></DD><DT CLASS="dt-description"><FONT COLOR=black><FONT SIZE=3><B>global variable:</B></FONT></FONT></DT><DD CLASS="dd-description"><FONT COLOR=black><FONT SIZE=3> A variable defined outside a function. Global
</DD><DT CLASS="dt-description">'''global variable:'''</DT><DD CLASS="dd-description"> A variable defined outside a function. Global
variables can be accessed from any function.
variables can be accessed from any function.
</FONT></FONT><A NAME="@default1013"></A></DD><DT CLASS="dt-description"><FONT COLOR=black><FONT SIZE=3><B>flag:</B></FONT></FONT></DT><DD CLASS="dd-description"><FONT COLOR=black><FONT SIZE=3> A boolean variable used to indicate whether a condition
</DD><DT CLASS="dt-description">'''flag:'''</DT><DD CLASS="dd-description"> A boolean variable used to indicate whether a condition
is true.
is true.
</FONT></FONT><A NAME="@default1014"></A></DD><DT CLASS="dt-description"><FONT COLOR=black><FONT SIZE=3><B>declaration:</B></FONT></FONT></DT><DD CLASS="dd-description"><FONT COLOR=black><FONT SIZE=3> A statement like </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>global</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> that tells the
</DD><DT CLASS="dt-description">'''declaration:'''</DT><DD CLASS="dd-description"> A statement like <TT>global</TT> that tells the
interpreter something about a variable.
interpreter something about a variable.
</FONT></FONT><A NAME="@default1015"></A></DD></DL><H2 CLASS="section"><A NAME="toc129"></A><A NAME="htoc142"><FONT COLOR=black><FONT SIZE=3>11.10</FONT></FONT></A><FONT COLOR=black><FONT SIZE=3>&#XA0;&#XA0;Exercises</FONT></FONT></H2><DIV CLASS="theorem"><FONT COLOR=black><FONT SIZE=3><B>Exercise&#XA0;8</B></FONT></FONT><FONT COLOR=black><FONT SIZE=3>&#XA0;&#XA0;<EM>
</DD></DL>=== 11.10&#XA0;&#XA0;Exercises ===
</EM></FONT></FONT><A NAME="@default1016"></A><P><FONT COLOR=black><FONT SIZE=3><EM>If you did Exercise&#XA0;</EM></FONT></FONT><A HREF="book011.html#duplicate"><FONT COLOR=black><FONT SIZE=3><EM>10.5</EM></FONT></FONT></A><FONT COLOR=black><FONT SIZE=3><EM>, you already have
 
a function named </EM></FONT></FONT><CODE><FONT COLOR=black><FONT SIZE=3><EM>has_duplicates</EM></FONT></FONT></CODE><FONT COLOR=black><FONT SIZE=3><EM> that takes a list
<DIV CLASS="theorem">'''Exercise&#XA0;8'''&#XA0;&#XA0;''
as a parameter and returns </EM></FONT></FONT><FONT COLOR=black><FONT SIZE=3><EM><TT>True</TT></EM></FONT></FONT><FONT COLOR=black><FONT SIZE=3><EM> if there is any object
''
that appears more than once in the list.</EM></FONT></FONT></P><P><FONT COLOR=black><FONT SIZE=3><EM>Use a dictionary to write a faster, simpler version of
''If you did Exercise&#XA0;''''10.5'''', you already have
</EM></FONT></FONT><CODE><FONT COLOR=black><FONT SIZE=3><EM>has_duplicates</EM></FONT></FONT></CODE><FONT COLOR=black><FONT SIZE=3><EM>.
a function named ''<CODE>''has_duplicates''</CODE>'' that takes a list
</EM></FONT></FONT></P></DIV><DIV CLASS="theorem"><FONT COLOR=black><FONT SIZE=3><B>Exercise&#XA0;9</B></FONT></FONT><FONT COLOR=black><FONT SIZE=3>&#XA0;&#XA0;<EM>
as a parameter and returns ''''<TT>True</TT>'''' if there is any object
</EM></FONT></FONT><A NAME="exrotatepairs"></A><P><A NAME="@default1017"></A><FONT COLOR=black><FONT SIZE=3><EM>
that appears more than once in the list.''
</EM></FONT></FONT><A NAME="@default1018"></A></P><P><FONT COLOR=black><FONT SIZE=3><EM>Two words are &#X201C;rotate pairs&#X201D; if you can rotate one of them
 
and get the other (see </EM></FONT></FONT><CODE><FONT COLOR=black><FONT SIZE=3><EM>rotate_word</EM></FONT></FONT></CODE><FONT COLOR=black><FONT SIZE=3><EM> in Exercise&#XA0;</EM></FONT></FONT><A HREF="book009.html#exrotate"><FONT COLOR=black><FONT SIZE=3><EM>8.12</EM></FONT></FONT></A><FONT COLOR=black><FONT SIZE=3><EM>).</EM></FONT></FONT></P><P><FONT COLOR=black><FONT SIZE=3><EM>Write a program that reads a wordlist and finds all the rotate
''Use a dictionary to write a faster, simpler version of
''<CODE>''has_duplicates''</CODE>''.
''
</DIV><DIV CLASS="theorem">'''Exercise&#XA0;9'''&#XA0;&#XA0;''
''
''
''
 
''Two words are &#X201C;rotate pairs&#X201D; if you can rotate one of them
and get the other (see ''<CODE>''rotate_word''</CODE>'' in Exercise&#XA0;''''8.12'''').''
 
''Write a program that reads a wordlist and finds all the rotate
pairs.
pairs.
</EM></FONT></FONT></P></DIV><DIV CLASS="theorem"><FONT COLOR=black><FONT SIZE=3><B>Exercise&#XA0;10</B></FONT></FONT><FONT COLOR=black><FONT SIZE=3>&#XA0;&#XA0;<EM>
''
</EM></FONT></FONT><A NAME="@default1019"></A><FONT COLOR=black><FONT SIZE=3><EM>
</DIV><DIV CLASS="theorem">'''Exercise&#XA0;10'''&#XA0;&#XA0;''
</EM></FONT></FONT><A NAME="@default1020"></A><P><FONT COLOR=black><FONT SIZE=3><EM>Here&#X2019;s another Puzzler from </EM></FONT></FONT><FONT COLOR=black><FONT SIZE=3>Car
''''
Talk</FONT></FONT><SUP><A NAME="text24" HREF="#note24"><FONT COLOR=black><FONT SIZE=3><EM>4</EM></FONT></FONT></A></SUP><FONT COLOR=black><FONT SIZE=3><EM>:</EM></FONT></FONT></P><BLOCKQUOTE CLASS="quote"><FONT COLOR=black><FONT SIZE=3><EM>
''
''Here&#X2019;s another Puzzler from ''Car
Talk<SUP>''4''</SUP>'':''
<BLOCKQUOTE CLASS="quote">''
This was sent in by a fellow named Dan O&#X2019;Leary. He came upon a common
This was sent in by a fellow named Dan O&#X2019;Leary. He came upon a common
one-syllable, five-letter word recently that has the following unique
one-syllable, five-letter word recently that has the following unique
Line 453: Line 713:
the same. Replace the first letter, that is, put it back and remove
the same. Replace the first letter, that is, put it back and remove
the second letter and the result is yet another homophone of the
the second letter and the result is yet another homophone of the
original word. And the question is, what&#X2019;s the word?</EM></FONT></FONT><P><FONT COLOR=black><FONT SIZE=3><EM>Now I&#X2019;m going to give you an example that doesn&#X2019;t work. Let&#X2019;s look at
original word. And the question is, what&#X2019;s the word?''
''Now I&#X2019;m going to give you an example that doesn&#X2019;t work. Let&#X2019;s look at
the five-letter word, &#X2018;wrack.&#X2019; W-R-A-C-K, you know like to &#X2018;wrack with
the five-letter word, &#X2018;wrack.&#X2019; W-R-A-C-K, you know like to &#X2018;wrack with
pain.&#X2019; If I remove the first letter, I am left with a four-letter
pain.&#X2019; If I remove the first letter, I am left with a four-letter
Line 460: Line 721:
put the &#X2018;w&#X2019; back, and remove the &#X2018;r,&#X2019; instead, you&#X2019;re left with the
put the &#X2018;w&#X2019; back, and remove the &#X2018;r,&#X2019; instead, you&#X2019;re left with the
word, &#X2018;wack,&#X2019; which is a real word, it&#X2019;s just not a homophone of the
word, &#X2018;wack,&#X2019; which is a real word, it&#X2019;s just not a homophone of the
other two words.</EM></FONT></FONT></P><P><FONT COLOR=black><FONT SIZE=3><EM>But there is, however, at least one word that Dan and we know of,
other two words.''
 
''But there is, however, at least one word that Dan and we know of,
which will yield two homophones if you remove either of the first two
which will yield two homophones if you remove either of the first two
letters to make two, new four-letter words. The question is, what&#X2019;s
letters to make two, new four-letter words. The question is, what&#X2019;s
the word?
the word?
</EM></FONT></FONT></P></BLOCKQUOTE><P><A NAME="@default1021"></A><FONT COLOR=black><FONT SIZE=3><EM>
''
</EM></FONT></FONT><A NAME="@default1022"></A><FONT COLOR=black><FONT SIZE=3><EM>
</BLOCKQUOTE>
</EM></FONT></FONT><A NAME="@default1023"></A></P><P><FONT COLOR=black><FONT SIZE=3><EM>You can use the dictionary from Exercise&#XA0;</EM></FONT></FONT><A HREF="#wordlist2"><FONT COLOR=black><FONT SIZE=3><EM>11.1</EM></FONT></FONT></A><FONT COLOR=black><FONT SIZE=3><EM> to check
''
whether a string is in the word list.</EM></FONT></FONT></P><P><FONT COLOR=black><FONT SIZE=3><EM>To check whether two words are homophones, you can use the CMU
''''
''
 
''You can use the dictionary from Exercise&#XA0;''''11.1'''' to check
whether a string is in the word list.''
 
''To check whether two words are homophones, you can use the CMU
Pronouncing Dictionary. You can download it from
Pronouncing Dictionary. You can download it from
</EM></FONT></FONT><FONT COLOR=black><FONT SIZE=3><EM><TT>www.speech.cs.cmu.edu/cgi-bin/cmudict</TT></EM></FONT></FONT><FONT COLOR=black><FONT SIZE=3><EM> or from
''''<TT>www.speech.cs.cmu.edu/cgi-bin/cmudict</TT>'''' or from
</EM></FONT></FONT><FONT COLOR=black><FONT SIZE=3><EM><TT>thinkpython.com/code/c06d</TT></EM></FONT></FONT><FONT COLOR=black><FONT SIZE=3><EM> and you can also download
''''<TT>thinkpython.com/code/c06d</TT>'''' and you can also download
</EM></FONT></FONT><FONT COLOR=black><FONT SIZE=3><EM><TT>thinkpython.com/code/pronounce.py</TT></EM></FONT></FONT><FONT COLOR=black><FONT SIZE=3><EM>, which provides a function
''''<TT>thinkpython.com/code/pronounce.py</TT>'''', which provides a function
named </EM></FONT></FONT><CODE><FONT COLOR=black><FONT SIZE=3><EM>read_dictionary</EM></FONT></FONT></CODE><FONT COLOR=black><FONT SIZE=3><EM> that reads the pronouncing dictionary and
named ''<CODE>''read_dictionary''</CODE>'' that reads the pronouncing dictionary and
returns a Python dictionary that maps from each word to a string that
returns a Python dictionary that maps from each word to a string that
describes its primary pronunciation.</EM></FONT></FONT></P><P><FONT COLOR=black><FONT SIZE=3><EM>Write a program that lists all the words that solve the Puzzler.
describes its primary pronunciation.''
You can see my solution at </EM></FONT></FONT><FONT COLOR=black><FONT SIZE=3><EM><TT>thinkpython.com/code/homophone.py</TT></EM></FONT></FONT><FONT COLOR=black><FONT SIZE=3><EM>.</EM></FONT></FONT></P></DIV><HR CLASS="footnoterule"><DL CLASS="thefootnotes"><DT CLASS="dt-thefootnotes"><FONT COLOR=black><FONT SIZE=3>
 
</FONT></FONT><A NAME="note21" HREF="#text21"><FONT COLOR=black><FONT SIZE=3>1</FONT></FONT></A></DT><DD CLASS="dd-thefootnotes"><FONT COLOR=black><FONT SIZE=3>See
''Write a program that lists all the words that solve the Puzzler.
You can see my solution at ''''<TT>thinkpython.com/code/homophone.py</TT>''''.''
</DIV><HR CLASS="footnoterule"><DL CLASS="thefootnotes"><DT CLASS="dt-thefootnotes">
1</DT><DD CLASS="dd-thefootnotes">See
<TT>wikipedia.org/wiki/Memoization</TT>
<TT>wikipedia.org/wiki/Memoization</TT>
</FONT></FONT></DD><DT CLASS="dt-thefootnotes"><A NAME="note22" HREF="#text22"><FONT COLOR=black><FONT SIZE=3>2</FONT></FONT></A></DT><DD CLASS="dd-thefootnotes"><FONT COLOR=black><FONT SIZE=3>In Python 3.0, type <TT>long</TT> is gone; all integers,
</DD><DT CLASS="dt-thefootnotes">2</DT><DD CLASS="dd-thefootnotes">In Python 3.0, type <TT>long</TT> is gone; all integers,
even really big ones, are type <TT>int</TT>.
even really big ones, are type <TT>int</TT>.
</FONT></FONT></DD><DT CLASS="dt-thefootnotes"><A NAME="note23" HREF="#text23"><FONT COLOR=black><FONT SIZE=3>3</FONT></FONT></A></DT><DD CLASS="dd-thefootnotes"><FONT COLOR=black><FONT SIZE=3><TT>wikipedia.org/wiki/RSA</TT>
</DD><DT CLASS="dt-thefootnotes">3</DT><DD CLASS="dd-thefootnotes"><TT>wikipedia.org/wiki/RSA</TT>
</FONT></FONT></DD><DT CLASS="dt-thefootnotes"><A NAME="note24" HREF="#text24"><FONT COLOR=black><FONT SIZE=3>4</FONT></FONT></A></DT><DD CLASS="dd-thefootnotes"><FONT COLOR=black><FONT SIZE=3><TT>www.cartalk.com/content/puzzler/transcripts/200717</TT>
</DD><DT CLASS="dt-thefootnotes">4</DT><DD CLASS="dd-thefootnotes"><TT>www.cartalk.com/content/puzzler/transcripts/200717</TT>
</FONT></FONT></DD></DL>
</DD></DL>
<HR>
<HR>
<A HREF="book011.html"><IMG SRC="previous_motif.gif" ALT="Previous"></A>
<IMG SRC="previous_motif.gif" ALT="Previous">
<A HREF="index.html"><IMG SRC="contents_motif.gif" ALT="Up"></A>
<IMG SRC="contents_motif.gif" ALT="Up">
<A HREF="book013.html"><IMG SRC="next_motif.gif" ALT="Next"></A>
<IMG SRC="next_motif.gif" ALT="Next">
</BODY>
</HTML>

Revision as of 23:09, 15 September 2008

Chapter 11  Dictionaries

A dictionary is like a list, but more general. In a list, the indices have to be integers; in a dictionary they can be (almost) any type.

You can think of a dictionary as a mapping between a set of indices (which are called keys) and a set of values. Each key maps to a value. The association of a key and a value is called a key-value pair or sometimes an item.

As an example, we’ll build a dictionary that maps from English to Spanish words, so the keys and the values are all strings.

The function dict creates a new dictionary with no items. Because dict is the name of a built-in function, you should avoid using it as a variable name.


>>> eng2sp = dict()
>>> print eng2sp
{}

The squiggly-brackets, {}, represent an empty dictionary. To add items to the dictionary, you can use square brackets:


>>> eng2sp['one'] = 'uno'

This line creates an item that maps from the key ’one’ to the value 'uno'. If we print the dictionary again, we see a key-value pair with a colon between the key and value:

>>> print eng2sp
{'one': 'uno'}

This output format is also an input format. For example, you can create a new dictionary with three items:

>>> eng2sp = {'one': 'uno', 'two': 'dos', 'three': 'tres'}

But if you print eng2sp, you might be surprised:

>>> print eng2sp
{'one': 'uno', 'three': 'tres', 'two': 'dos'}

The order of the key-value pairs is not the same. In fact, if you type the same example on your computer, you might get a different result. In general, the order of items in a dictionary is unpredictable.

But that’s not a problem because the elements of a dictionary are never indexed with integer indices. Instead, you use the keys to look up the corresponding values:

>>> print eng2sp['two']
'dos'

The key ’two’ always maps to the value 'dos' so the order of the items doesn’t matter.

If the key isn’t in the dictionary, you get an exception:


>>> print eng2sp['four']
KeyError: 'four'

The len function works on dictionaries; it returns the number of key-value pairs:


>>> len(eng2sp)
3

The in operator works on dictionaries; it tells you whether something appears as a key in the dictionary (appearing as a value is not good enough).



>>> 'one' in eng2sp
True
>>> 'uno' in eng2sp
False

To see whether something appears as a value in a dictionary, you can use the method values, which returns the values as a list, and then use the in operator:


>>> vals = eng2sp.values()
>>> 'uno' in vals
True

The in operator uses different algorithms for lists and dictionaries. For lists, it uses a search algorithm, as in Section 8.6. As the list gets longer, the search time gets longer in direct proportion. For dictionaries, Python uses an algorithm called a hashtable that has a remarkable property: the in operator takes about the same amount of time no matter how many items there are in a dictionary. I won’t explain how that’s possible, but you can read more about it at wikipedia.org/wiki/Hash_table.

Exercise 1  

Write a function that reads the words in 'words.txt' and stores them as keys in a dictionary. It doesn’t matter what the values are. Then you can use the 'in' operator as a fast way to check whether a string is in the dictionary.

If you did Exercise '10.8', you can compare the speed of this implementation with the list 'in' operator and the bisection search.

=== 11.1  Dictionary as a set of counters ===



Suppose you are given a string and you want to count how many times each letter appears. There are several ways you could do it:

  • You could create 26 variables, one for each letter of the

alphabet. Then you could traverse the string and, for each character, increment the corresponding counter, probably using a chained conditional.

  • You could create a list with 26 elements. Then you could

convert each character to a number (using the built-in function ord), use the number as an index into the list, and increment the appropriate counter.

  • You could create a dictionary with characters as keys

and counters as the corresponding values. The first time you see a character, you would add an item to the dictionary. After that you would increment the value of an existing item.

Each of these options performs the same computation, but each of them implements that computation in a different way.

An implementation is a way of performing a computation; some implementations are better than others. For example, an advantage of the dictionary implementation is that we don’t have to know ahead of time which letters appear in the string and we only have to make room for the letters that do appear.

Here is what the code might look like:

def histogram(s):
    d = dict()
    for c in s:
        if c not in d:
            d[c] = 1
        else:
            d[c] += 1
    return d

The name of the function is histogram, which is a statistical term for a set of counters (or frequencies).



The first line of the function creates an empty dictionary. The for loop traverses the string. Each time through the loop, if the character c is not in the dictionary, we create a new item with key c and the initial value 1 (since we have seen this letter once). If c is already in the dictionary we increment d[c].

Here’s how it works:

>>> h = histogram('brontosaurus')
>>> print h
{'a': 1, 'b': 1, 'o': 2, 'n': 1, 's': 2, 'r': 2, 'u': 2, 't': 1}

The histogram indicates that the letters ’a’ and 'b' appear once; 'o' appears twice, and so on.

Exercise 2  

Dictionaries have a method called 'get' that takes a key and a default value. If the key appears in the dictionary, 'get' returns the corresponding value; otherwise it returns the default value. For example:

''>>> h = histogram('a')
>>> print h
{'a': 1}
>>> h.get('a', 0)
1
>>> h.get('b', 0)
0
''

Use 'get' to write 'histogram' more concisely. You should be able to eliminate the 'if' statement.

=== 11.2  Looping and dictionaries ===



If you use a dictionary in a for statement, it traverses the keys of the dictionary. For example, print_hist prints each key and the corresponding value:

def print_hist(h):
    for c in h:
        print c, h[c]

Here’s what the output looks like:

>>> h = histogram('parrot')
>>> print_hist(h)
a 1
p 1
r 2
t 1
o 1

Again, the keys are in no particular order.

Exercise 3  

Dictionaries have a method called 'keys' that returns the keys of the dictionary, in no particular order, as a list.

Modify print_hist to print the keys and their values in alphabetical order.

=== 11.3  Reverse lookup ===




Given a dictionary d and a key k, it is easy to find the corresponding value v = d[k]. This operation is called a lookup.

But what if you have v and you want to find k? You have two problems: first, there might be more than one key that maps to the value v. Depending on the application, you might be able to pick one, or you might have to make a list that contains all of them. Second, there is no simple syntax to do a reverse lookup; you have to search.

Here is a function that takes a value and returns the first key that maps to that value:

def reverse_lookup(d, v):
    for k in d:
        if d[k] == v:
            return k
    raise ValueError

This function is yet another example of the search pattern, but it uses a feature we haven’t seen before, raise. The raise statement causes an exception; in this case it causes a ValueError, which generally indicates that there is something wrong with the value of a parameter.





If we get to the end of the loop, that means v doesn’t appear in the dictionary as a value, so we raise an exception.

Here is an example of a successful reverse lookup:

>>> h = histogram('parrot')
>>> k = reverse_lookup(h, 2)
>>> print k
r

And an unsuccessful one:

>>> k = reverse_lookup(h, 3)
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "<stdin>", line 5, in reverse_lookup
ValueError

The result when you raise an exception is the same as when Python raises one: it prints a traceback and an error message.



The raise statement takes a detailed error message as an optional argument. For example:

>>> raise ValueError, 'value does not appear in the dictionary'
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
ValueError: value does not appear in the dictionary

A reverse lookup is much slower than a forward lookup; if you have to do it often, or if the dictionary gets big, the performance of your program will suffer.

Exercise 4  

Modify reverse_lookup so that it builds and returns a list of all keys that map to 'v', or an empty list if there are none.

=== 11.4  Dictionaries and lists ===

Lists can appear as values in a dictionary. For example, if you were given a dictionary that maps from letters to frequencies, you might want to invert it; that is, create a dictionary that maps from frequencies to letters. Since there might be several letters with the same frequency, each value in the inverted dictionary should be a list of letters.



Here is a function that inverts a dictionary:

def invert_dict(d):
    inv = dict()
    for key in d:
        val = d[key]
        if val not in inv:
            inv[val] = [key]
        else:
            inv[val].append(key)
    return inv

Each time through the loop, key gets a key from d and val gets the corresponding value. If val is not in inv, that means we haven’t seen it before, so we create a new item and initialize it with a singleton (a list that contains a single element). Otherwise we have seen this value before, so we append the corresponding key to the list.

Here is an example:

>>> hist = histogram('parrot')
>>> print hist
{'a': 1, 'p': 1, 'r': 2, 't': 1, 'o': 1}
>>> inv = invert_dict(hist)
>>> print inv
{1: ['a', 'p', 't', 'o'], 2: ['r']}

And here is a diagram showing hist and inv:


<IMG SRC="book018.png">

A dictionary is represented as a box with the type dict above it and the key-value pairs inside. If the values are integers, floats or strings, I usually draw them inside the box, but I usually draw lists outside the box, just to keep the diagram simple.

Lists can be values in a dictionary, as this example shows, but they cannot be keys. Here’s what happens if you try:


>>> t = [1, 2, 3]
>>> d = dict()
>>> d[t] = 'oops'
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
TypeError: list objects are unhashable

I mentioned earlier that a dictionary is implemented using a hashtable and that means that the keys have to be hashable.



A hash is a function that takes a value (of any kind) and returns an integer. Dictionaries use these integers, called hash values, to store and look up key-value pairs.

This system works fine if the keys are immutable. But if the keys are mutable, like lists, bad things happen. For example, when you create a key-value pair, Python hashes the key and stores it in the corresponding location. If you modify the key and then hash it again, it would go to a different location. In that case you might have two entries for the same key, or you might not be able to find a key. Either way, the dictionary wouldn’t work correctly.

That’s why the keys have to be hashable, and why mutable types like lists aren’t. The simplest way to get around this limitation is to use tuples, which we will see in the next chapter.

Since dictionaries are mutable, they can’t be used as keys, but they can be used as values.

Exercise 5  

Read the documentation of the dictionary method 'setdefault' and use it to write a more concise version of invert_dict.

=== 11.5  Memos ===

If you played with the fibonacci function from Section 6.7, you might have noticed that the bigger the argument you provide, the longer the function takes to run. Furthermore, the run time increases very quickly.



To understand why, consider this call graph for fibonacci with n=4:

<IMG SRC="book019.png">

A call graph shows a set of function frames, with lines connecting each frame to the frames of the functions it calls. At the top of the graph, fibonacci with n=4 calls fibonacci with n=3 and n=2. In turn, fibonacci with n=3 calls fibonacci with n=2 and n=1. And so on.



Count how many times fibonacci(0) and fibonacci(1) are called. This is an inefficient solution to the problem, and it gets worse as the argument gets bigger.

One solution is to keep track of values that have already been computed by storing them in a dictionary. A previously computed value that is stored for later use is called a memo1. Here is an implementation of fibonacci using memos:

known = {0:0, 1:1}

def fibonacci(n):
    if n in known:
        return known[n]

    res = fibonacci(n-1) + fibonacci(n-2)
    known[n] = res
    return res

known is a dictionary that keeps track of the Fibonacci numbers we already know. It starts with two items: 0 maps to 0 and 1 maps to 1.

Whenever fibonacci is called, it checks known. If the result is already there, it can return immediately. Otherwise it has to compute the new value, add it to the dictionary, and return it.

Exercise 6  

Run this version of 'fibonacci' and the original with a range of parameters and compare their run times.

=== 11.6  Global variables ===



In the previous example, known is created outside the function, so it belongs to the special frame called __main__. Variables in __main__ are sometimes called global because they can be accessed from any function. Unlike local variables, which disappear when their function ends, global variables persist from one function call to the next.

It is common to use global variables for flags; that is, boolean variables that indicate (“flag”) whether a condition is true. For example, some programs use a flag named verbose to control the level of detail in the output:

verbose = True

def example1():
    if verbose:
        print 'Running example1'

If you try to reassign a global variable, you might be surprised. The following example is supposed to keep track of whether the function has been called:


been_called = False

def example2():
    been_called = True         # WRONG

But if you run it you will see that the value of been_called doesn’t change. The problem is that example2 creates a new local variable named been_called. The local variable goes away when the function ends, and has no effect on the global variable.



To reassign a global variable inside a function you have to declare the global variable before you use it:

been_called = False

def example2():
    global been_called 
    been_called = True

The global statement tells the interpreter something like, “In this function, when I say been_called, I mean the global variable; don’t create a local one.”



Here’s an example that tries to update a global variable:

count = 0

def example3():
    count = count + 1          # WRONG

If you run it you get:


UnboundLocalError: local variable 'count' referenced before assignment

Python assumes that count is local, which means that you are reading it before writing it. The solution, again, is to declare count global.

def example3():
    global count
    count += 1

If the global value is mutable, you can modify it without declaring it:

known = {0:0, 1:1}

def example4():
    known[2] = 1

So you can add, remove and replace elements of a global list or dictionary, but if you want to reassign the variable, you have to declare it:

def example5():
    global known
    known = dict()

=== 11.7  Long integers ===



If you compute fibonacci(50), you get:

>>> fibonacci(50)
12586269025L

The L at the end indicates that the result is a long integer2, or type long.

Values with type int have a limited range; long integers can be arbitrarily big, but as they get bigger they consume more space and time.

The mathematical operators work on long integers, and the functions in the math module, too, so in general any code that works with int will also work with long.

Any time the result of a computation is too big to be represented with an integer, Python converts the result as a long integer:

>>> 1000 * 1000
1000000
>>> 100000 * 100000
10000000000L

In the first case the result has type int; in the second case it is long.

Exercise 7  

'

Exponentiation of large integers is the basis of common algorithms for public-key encryption. Read the Wikipedia page on the RSA algorithm3 and write functions to encode and decode messages.

=== 11.8  Debugging ===



As you work with bigger datasets it can become unwieldy to debug by printing and checking data by hand. Here are some suggestions for debugging large datasets:

Scale down the input:
If possible, reduce the size of the dataset. For example if the program reads a text file, start with just the first 10 lines, or with the smallest example you can find. You can either edit the files themselves, or (better) modify the program so it reads only the first n lines. If there is an error, you can reduce n to the smallest value that manifests the error, and then increase it gradually as you find and correct errors.
Check summaries and types:
Instead of printing and checking the entire dataset, consider printing summaries of the data: for example, the number of items in a dictionary or the total of a list of numbers. A common cause of runtime errors is a value that is not the right type. For debugging this kind of error, it is often enough to print the type of a value.
Write self-checks:
Sometimes you can write code to check for errors automatically. For example, if you are computing the average of a list of numbers, you could check that the result is not greater than the largest element in the list or less than the smallest. This is called a “sanity check” because it detects results that are “insane.” Another kind of check compares the results of two different computations to see if they are consistent. This is called a “consistency check.”
Pretty print the output:
Formatting debugging output can make it easier to spot an error. We saw an example in Section 6.9. The pprint module provides a pprint function that displays built-in types in a more human-readable format.

Again, time you spend building scaffolding can reduce the time you spend debugging.

11.9  Glossary

dictionary:
A mapping from a set of keys to their corresponding values.
key-value pair:
The representation of the mapping from a key to a value.
item:
Another name for a key-value pair.
key:
An object that appears in a dictionary as the first part of a key-value pair.
value:
An object that appears in a dictionary as the second part of a key-value pair. This is more specific than our previous use of the word “value.”
implementation:
A way of performing a computation.
hashtable:
The algorithm used to implement Python dictionaries.
hash function:
A function used by a hashtable to compute the location for a key.
hashable:
A type that has a hash function. Immutable types like integers, floats and strings are hashable; mutable types like lists and dictionaries are not.
lookup:
A dictionary operation that takes a key and finds the corresponding value.
reverse lookup:
A dictionary operation that takes a value and finds one or more keys that map to it.
singleton:
A list (or other sequence) with a single element.
call graph:
A diagram that shows every frame created during the execution of a program, with an arrow from each caller to each callee.
histogram:
A set of counters.
memo:
A computed value stored to avoid unnecessary future computation.
global variable:
A variable defined outside a function. Global variables can be accessed from any function.
flag:
A boolean variable used to indicate whether a condition is true.
declaration:
A statement like global that tells the interpreter something about a variable.

=== 11.10  Exercises ===

Exercise 8  

If you did Exercise '10.5', you already have a function named has_duplicates that takes a list as a parameter and returns 'True' if there is any object that appears more than once in the list.

Use a dictionary to write a faster, simpler version of has_duplicates.

Exercise 9  

Two words are “rotate pairs” if you can rotate one of them and get the other (see rotate_word in Exercise '8.12').

Write a program that reads a wordlist and finds all the rotate pairs.

Exercise 10  

' Here’s another Puzzler from Car Talk4:

This was sent in by a fellow named Dan O’Leary. He came upon a common one-syllable, five-letter word recently that has the following unique property. When you remove the first letter, the remaining letters form a homophone of the original word, that is a word that sounds exactly the same. Replace the first letter, that is, put it back and remove the second letter and the result is yet another homophone of the original word. And the question is, what’s the word? Now I’m going to give you an example that doesn’t work. Let’s look at the five-letter word, ‘wrack.’ W-R-A-C-K, you know like to ‘wrack with pain.’ If I remove the first letter, I am left with a four-letter word, ’R-A-C-K.’ As in, ‘Holy cow, did you see the rack on that buck! It must have been a nine-pointer!’ It’s a perfect homophone. If you put the ‘w’ back, and remove the ‘r,’ instead, you’re left with the word, ‘wack,’ which is a real word, it’s just not a homophone of the other two words.

But there is, however, at least one word that Dan and we know of, which will yield two homophones if you remove either of the first two letters to make two, new four-letter words. The question is, what’s the word?

'

You can use the dictionary from Exercise '11.1' to check whether a string is in the word list.

To check whether two words are homophones, you can use the CMU Pronouncing Dictionary. You can download it from 'www.speech.cs.cmu.edu/cgi-bin/cmudict' or from 'thinkpython.com/code/c06d' and you can also download 'thinkpython.com/code/pronounce.py', which provides a function named read_dictionary that reads the pronouncing dictionary and returns a Python dictionary that maps from each word to a string that describes its primary pronunciation.

Write a program that lists all the words that solve the Puzzler. You can see my solution at 'thinkpython.com/code/homophone.py'.


1
See wikipedia.org/wiki/Memoization
2
In Python 3.0, type long is gone; all integers, even really big ones, are type int.
3
wikipedia.org/wiki/RSA
4
www.cartalk.com/content/puzzler/transcripts/200717

<IMG SRC="previous_motif.gif" ALT="Previous"> <IMG SRC="contents_motif.gif" ALT="Up"> <IMG SRC="next_motif.gif" ALT="Next">