Jump to content

Archive:Think Python/Tuples: 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;12&#XA0;&#XA0;Tuples ==
<META name="GENERATOR" content="hevea 1.10">
 
<LINK rel="stylesheet" type="text/css" href="book.css">
 
<TITLE>Tuples</TITLE>
 
</HEAD>
=== 12.1&#XA0;&#XA0;Tuples are immutable ===
<BODY >
 
<A HREF="book012.html"><IMG SRC="previous_motif.gif" ALT="Previous"></A>
 
<A HREF="index.html"><IMG SRC="contents_motif.gif" ALT="Up"></A>
 
<A HREF="book014.html"><IMG SRC="next_motif.gif" ALT="Next"></A>
 
<HR>
 
<H1 CLASS="chapter"><A NAME="htoc143"><FONT COLOR=black><FONT SIZE=3>Chapter&#XA0;12</FONT></FONT></A><FONT COLOR=black><FONT SIZE=3>&#XA0;&#XA0;Tuples</FONT></FONT></H1><P><FONT COLOR=black><FONT SIZE=3>
A tuple is a sequence of values. The values can be any type, and
</FONT></FONT><A NAME="tuplechap"></A></P><H2 CLASS="section"><A NAME="toc130"></A><A NAME="htoc144"><FONT COLOR=black><FONT SIZE=3>12.1</FONT></FONT></A><FONT COLOR=black><FONT SIZE=3>&#XA0;&#XA0;Tuples are immutable</FONT></FONT></H2><P><A NAME="@default1024"></A><FONT COLOR=black><FONT SIZE=3>
</FONT></FONT><A NAME="@default1025"></A><FONT COLOR=black><FONT SIZE=3>
</FONT></FONT><A NAME="@default1026"></A></P><P><FONT COLOR=black><FONT SIZE=3>A tuple is a sequence of values. The values can be any type, and
they are indexed by integers, so in that respect tuples are a lot
they are indexed by integers, so in that respect tuples are a lot
like lists. The important difference is that tuples are immutable.</FONT></FONT></P><P><A NAME="@default1027"></A><FONT COLOR=black><FONT SIZE=3>
like lists. The important difference is that tuples are immutable.
</FONT></FONT><A NAME="@default1028"></A></P><P><FONT COLOR=black><FONT SIZE=3>Syntactically, a tuple is a comma-separated list of values:</FONT></FONT></P><PRE CLASS="verbatim"><FONT COLOR=blue><FONT SIZE=4>&gt;&gt;&gt; t = 'a', 'b', 'c', 'd', 'e'
 
</FONT></FONT></PRE><P><FONT COLOR=black><FONT SIZE=3>Although it is not necessary, it is common to enclose tuples in
 
parentheses:</FONT></FONT></P><P><A NAME="@default1029"></A></P><PRE CLASS="verbatim"><FONT COLOR=blue><FONT SIZE=4>&gt;&gt;&gt; t = ('a', 'b', 'c', 'd', 'e')
 
</FONT></FONT></PRE><P><FONT COLOR=black><FONT SIZE=3>To create a tuple with a single element, you have to include the final
 
comma:</FONT></FONT></P><P><A NAME="@default1030"></A><FONT COLOR=black><FONT SIZE=3>
Syntactically, a tuple is a comma-separated list of values:
</FONT></FONT><A NAME="@default1031"></A></P><PRE CLASS="verbatim"><FONT COLOR=blue><FONT SIZE=4>&gt;&gt;&gt; t1 = ('a',)
<PRE CLASS="verbatim">&gt;&gt;&gt; t = 'a', 'b', 'c', 'd', 'e'
</PRE>
Although it is not necessary, it is common to enclose tuples in
parentheses:
 
<PRE CLASS="verbatim">&gt;&gt;&gt; t = ('a', 'b', 'c', 'd', 'e')
</PRE>
To create a tuple with a single element, you have to include the final
comma:
 
 
 
<PRE CLASS="verbatim">&gt;&gt;&gt; t1 = ('a',)
&gt;&gt;&gt; type(t1)
&gt;&gt;&gt; type(t1)
&lt;type 'tuple'&gt;
&lt;type 'tuple'&gt;
</FONT></FONT></PRE><P><FONT COLOR=black><FONT SIZE=3>Without the comma, Python treats </FONT></FONT><CODE><FONT COLOR=black><FONT SIZE=3>('a')</FONT></FONT></CODE><FONT COLOR=black><FONT SIZE=3> as a string in
</PRE>
parentheses:</FONT></FONT></P><PRE CLASS="verbatim"><FONT COLOR=blue><FONT SIZE=4>&gt;&gt;&gt; t2 = ('a')
Without the comma, Python treats <CODE>('a')</CODE> as a string in
parentheses:
<PRE CLASS="verbatim">&gt;&gt;&gt; t2 = ('a')
&gt;&gt;&gt; type(t2)
&gt;&gt;&gt; type(t2)
&lt;type 'str'&gt;
&lt;type 'str'&gt;
</FONT></FONT></PRE><P><FONT COLOR=black><FONT SIZE=3>Another way to create a tuple is the built-in function </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>tuple</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3>.
</PRE>
With no argument, it creates an empty tuple:</FONT></FONT></P><P><A NAME="@default1032"></A><FONT COLOR=black><FONT SIZE=3>
Another way to create a tuple is the built-in function <TT>tuple</TT>.
</FONT></FONT><A NAME="@default1033"></A></P><PRE CLASS="verbatim"><FONT COLOR=blue><FONT SIZE=4>&gt;&gt;&gt; t = tuple()
With no argument, it creates an empty tuple:
 
 
 
<PRE CLASS="verbatim">&gt;&gt;&gt; t = tuple()
&gt;&gt;&gt; print t
&gt;&gt;&gt; print t
()
()
</FONT></FONT></PRE><P><FONT COLOR=black><FONT SIZE=3>If the argument is a sequence (string, list or tuple), the result
</PRE>
is a tuple with the elements of the sequence:</FONT></FONT></P><PRE CLASS="verbatim"><FONT COLOR=blue><FONT SIZE=4>&gt;&gt;&gt; t = tuple('lupins')
If the argument is a sequence (string, list or tuple), the result
is a tuple with the elements of the sequence:
<PRE CLASS="verbatim">&gt;&gt;&gt; t = tuple('lupins')
&gt;&gt;&gt; print t
&gt;&gt;&gt; print t
('l', 'u', 'p', 'i', 'n', 's')
('l', 'u', 'p', 'i', 'n', 's')
</FONT></FONT></PRE><P><FONT COLOR=black><FONT SIZE=3>Because </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>tuple</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> is the name of a built-in function, you should
</PRE>
avoid using it as a variable name.</FONT></FONT></P><P><FONT COLOR=black><FONT SIZE=3>Most list operators also work on tuples. The bracket operator
Because <TT>tuple</TT> is the name of a built-in function, you should
indexes an element:</FONT></FONT></P><P><A NAME="@default1034"></A><FONT COLOR=black><FONT SIZE=3>
avoid using it as a variable name.
</FONT></FONT><A NAME="@default1035"></A></P><PRE CLASS="verbatim"><FONT COLOR=blue><FONT SIZE=4>&gt;&gt;&gt; t = ('a', 'b', 'c', 'd', 'e')
 
Most list operators also work on tuples. The bracket operator
indexes an element:
 
 
 
<PRE CLASS="verbatim">&gt;&gt;&gt; t = ('a', 'b', 'c', 'd', 'e')
&gt;&gt;&gt; print t[0]
&gt;&gt;&gt; print t[0]
'a'
'a'
</FONT></FONT></PRE><P><FONT COLOR=black><FONT SIZE=3>And the slice operator selects a range of elements.</FONT></FONT></P><P><A NAME="@default1036"></A><FONT COLOR=black><FONT SIZE=3>
</PRE>
</FONT></FONT><A NAME="@default1037"></A><FONT COLOR=black><FONT SIZE=3>
And the slice operator selects a range of elements.
</FONT></FONT><A NAME="@default1038"></A><FONT COLOR=black><FONT SIZE=3>
 
</FONT></FONT><A NAME="@default1039"></A></P><PRE CLASS="verbatim"><FONT COLOR=blue><FONT SIZE=4>&gt;&gt;&gt; print t[1:3]
 
 
 
 
<PRE CLASS="verbatim">&gt;&gt;&gt; print t[1:3]
('b', 'c')
('b', 'c')
</FONT></FONT></PRE><P><FONT COLOR=black><FONT SIZE=3>But if you try to modify one of the elements of the tuple, you get
</PRE>
an error:</FONT></FONT></P><P><A NAME="@default1040"></A><FONT COLOR=black><FONT SIZE=3>
But if you try to modify one of the elements of the tuple, you get
</FONT></FONT><A NAME="@default1041"></A><FONT COLOR=black><FONT SIZE=3>
an error:
</FONT></FONT><A NAME="@default1042"></A><FONT COLOR=black><FONT SIZE=3>
 
</FONT></FONT><A NAME="@default1043"></A></P><PRE CLASS="verbatim"><FONT COLOR=blue><FONT SIZE=4>&gt;&gt;&gt; t[0] = 'A'
 
 
 
 
<PRE CLASS="verbatim">&gt;&gt;&gt; t[0] = 'A'
TypeError: object doesn't support item assignment
TypeError: object doesn't support item assignment
</FONT></FONT></PRE><P><FONT COLOR=black><FONT SIZE=3>You can&#X2019;t modify the elements of a tuple, but you can replace
</PRE>
one tuple with another:</FONT></FONT></P><PRE CLASS="verbatim"><FONT COLOR=blue><FONT SIZE=4>&gt;&gt;&gt; t = ('A',) + t[1:]
You can&#X2019;t modify the elements of a tuple, but you can replace
one tuple with another:
<PRE CLASS="verbatim">&gt;&gt;&gt; t = ('A',) + t[1:]
&gt;&gt;&gt; print t
&gt;&gt;&gt; print t
('A', 'b', 'c', 'd', 'e')
('A', 'b', 'c', 'd', 'e')
</FONT></FONT></PRE><H2 CLASS="section"><A NAME="toc131"></A><A NAME="htoc145"><FONT COLOR=black><FONT SIZE=3>12.2</FONT></FONT></A><FONT COLOR=black><FONT SIZE=3>&#XA0;&#XA0;Tuple assignment</FONT></FONT></H2><P><FONT COLOR=black><FONT SIZE=3>
</PRE>=== 12.2&#XA0;&#XA0;Tuple assignment ===
</FONT></FONT><A NAME="tuple assignment"></A></P><P><A NAME="@default1044"></A><FONT COLOR=black><FONT SIZE=3>
 
</FONT></FONT><A NAME="@default1045"></A><FONT COLOR=black><FONT SIZE=3>
 
</FONT></FONT><A NAME="@default1046"></A><FONT COLOR=black><FONT SIZE=3>
 
</FONT></FONT><A NAME="@default1047"></A></P><P><FONT COLOR=black><FONT SIZE=3>It is often useful to swap the values of two variables.
 
 
 
 
 
 
It is often useful to swap the values of two variables.
With conventional assignments, you have to use a temporary
With conventional assignments, you have to use a temporary
variable. For example, to swap </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>a</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> and </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>b</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3>:</FONT></FONT></P><PRE CLASS="verbatim"><FONT COLOR=blue><FONT SIZE=4>&gt;&gt;&gt; temp = a
variable. For example, to swap <TT>a</TT> and <TT>b</TT>:
<PRE CLASS="verbatim">&gt;&gt;&gt; temp = a
&gt;&gt;&gt; a = b
&gt;&gt;&gt; a = b
&gt;&gt;&gt; b = temp
&gt;&gt;&gt; b = temp
</FONT></FONT></PRE><P><FONT COLOR=black><FONT SIZE=3>This solution is cumbersome; </FONT></FONT><FONT COLOR=black><FONT SIZE=3><B>tuple assignment</B></FONT></FONT><FONT COLOR=black><FONT SIZE=3> is more elegant:</FONT></FONT></P><PRE CLASS="verbatim"><FONT COLOR=blue><FONT SIZE=4>&gt;&gt;&gt; a, b = b, a
</PRE>
</FONT></FONT></PRE><P><FONT COLOR=black><FONT SIZE=3>The left side is a tuple of variables; the right side is a tuple of
This solution is cumbersome; '''tuple assignment''' is more elegant:
<PRE CLASS="verbatim">&gt;&gt;&gt; a, b = b, a
</PRE>
The left side is a tuple of variables; the right side is a tuple of
expressions. Each value is assigned to its respective variable.  
expressions. Each value is assigned to its respective variable.  
All the expressions on the right side are evaluated before any
All the expressions on the right side are evaluated before any
of the assignments.</FONT></FONT></P><P><FONT COLOR=black><FONT SIZE=3>The number of variables on the left and the number of
of the assignments.
values on the right have to be the same:</FONT></FONT></P><P><A NAME="@default1048"></A><FONT COLOR=black><FONT SIZE=3>
 
</FONT></FONT><A NAME="@default1049"></A></P><PRE CLASS="verbatim"><FONT COLOR=blue><FONT SIZE=4>&gt;&gt;&gt; a, b = 1, 2, 3
The number of variables on the left and the number of
values on the right have to be the same:
 
 
 
<PRE CLASS="verbatim">&gt;&gt;&gt; a, b = 1, 2, 3
ValueError: too many values to unpack
ValueError: too many values to unpack
</FONT></FONT></PRE><P><FONT COLOR=black><FONT SIZE=3>More generally, the right side can be any kind of sequence
</PRE>
More generally, the right side can be any kind of sequence
(string, list or tuple). For example, to split an email address
(string, list or tuple). For example, to split an email address
into a user name and a domain, you could write:</FONT></FONT></P><P><A NAME="@default1050"></A><FONT COLOR=black><FONT SIZE=3>
into a user name and a domain, you could write:
</FONT></FONT><A NAME="@default1051"></A><FONT COLOR=black><FONT SIZE=3>
 
</FONT></FONT><A NAME="@default1052"></A></P><PRE CLASS="verbatim"><FONT COLOR=blue><FONT SIZE=4>&gt;&gt;&gt; addr = 'monty@python.org'
 
 
 
<PRE CLASS="verbatim">&gt;&gt;&gt; addr = 'monty@python.org'
&gt;&gt;&gt; uname, domain = addr.split('@')
&gt;&gt;&gt; uname, domain = addr.split('@')
</FONT></FONT></PRE><P><FONT COLOR=black><FONT SIZE=3>The return value from </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>split</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> is a list with two elements;
</PRE>
the first element is assigned to </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>uname</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3>, the second to
The return value from <TT>split</TT> is a list with two elements;
</FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>domain</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3>.</FONT></FONT></P><PRE CLASS="verbatim"><FONT COLOR=blue><FONT SIZE=4>&gt;&gt;&gt; print uname
the first element is assigned to <TT>uname</TT>, the second to
<TT>domain</TT>.
<PRE CLASS="verbatim">&gt;&gt;&gt; print uname
monty
monty
&gt;&gt;&gt; print domain
&gt;&gt;&gt; print domain
python.org
python.org
</FONT></FONT></PRE><H2 CLASS="section"><A NAME="toc132"></A><A NAME="htoc146"><FONT COLOR=black><FONT SIZE=3>12.3</FONT></FONT></A><FONT COLOR=black><FONT SIZE=3>&#XA0;&#XA0;Tuples as return values</FONT></FONT></H2><P><A NAME="@default1053"></A><FONT COLOR=black><FONT SIZE=3>
</PRE>=== 12.3&#XA0;&#XA0;Tuples as return values ===
</FONT></FONT><A NAME="@default1054"></A><FONT COLOR=black><FONT SIZE=3>
 
</FONT></FONT><A NAME="@default1055"></A><FONT COLOR=black><FONT SIZE=3>
 
</FONT></FONT><A NAME="@default1056"></A></P><P><FONT COLOR=black><FONT SIZE=3>Strictly speaking, a function can only return one value, but
 
 
 
 
Strictly speaking, a function can only return one value, but
if the value is a tuple, the effect is the same as returning
if the value is a tuple, the effect is the same as returning
multiple values. For example, if you want to divide two integers
multiple values. For example, if you want to divide two integers
and compute the quotient and remainder, it is inefficient to
and compute the quotient and remainder, it is inefficient to
compute </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>x/y</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> and then </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>x%y</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3>. It is better to compute
compute <TT>x/y</TT> and then <TT>x%y</TT>. It is better to compute
them both at the same time.</FONT></FONT></P><P><A NAME="@default1057"></A></P><P><FONT COLOR=black><FONT SIZE=3>The built-in function </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>divmod</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> takes two arguments and
them both at the same time.
 
The built-in function <TT>divmod</TT> takes two arguments and
returns a tuple of two values, the quotient and remainder.
returns a tuple of two values, the quotient and remainder.
You can store the result as a tuple:</FONT></FONT></P><PRE CLASS="verbatim"><FONT COLOR=blue><FONT SIZE=4>&gt;&gt;&gt; t = divmod(7, 3)
You can store the result as a tuple:
<PRE CLASS="verbatim">&gt;&gt;&gt; t = divmod(7, 3)
&gt;&gt;&gt; print t
&gt;&gt;&gt; print t
(2, 1)
(2, 1)
</FONT></FONT></PRE><P><FONT COLOR=black><FONT SIZE=3>Or use tuple assignment to store the elements separately:</FONT></FONT></P><P><A NAME="@default1058"></A><FONT COLOR=black><FONT SIZE=3>
</PRE>
</FONT></FONT><A NAME="@default1059"></A></P><PRE CLASS="verbatim"><FONT COLOR=blue><FONT SIZE=4>&gt;&gt;&gt; quot, rem = divmod(7, 3)
Or use tuple assignment to store the elements separately:
 
 
 
<PRE CLASS="verbatim">&gt;&gt;&gt; quot, rem = divmod(7, 3)
&gt;&gt;&gt; print quot
&gt;&gt;&gt; print quot
2
2
&gt;&gt;&gt; print rem
&gt;&gt;&gt; print rem
1
1
</FONT></FONT></PRE><P><FONT COLOR=black><FONT SIZE=3>Here is an example of a function that returns a tuple:</FONT></FONT></P><PRE CLASS="verbatim"><FONT COLOR=blue><FONT SIZE=4>def min_max(t):
</PRE>
Here is an example of a function that returns a tuple:
<PRE CLASS="verbatim">def min_max(t):
     return min(t), max(t)
     return min(t), max(t)
</FONT></FONT></PRE><P><FONT COLOR=black><FONT SIZE=3><TT>max</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> and </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>min</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> are built-in functions that find
</PRE>
the largest and smallest elements of a sequence. </FONT></FONT><CODE><FONT COLOR=black><FONT SIZE=3>min_max</FONT></FONT></CODE><FONT COLOR=black><FONT SIZE=3>
<TT>max</TT> and <TT>min</TT> are built-in functions that find
computes both and returns a tuple of two values.</FONT></FONT></P><P><A NAME="@default1060"></A><FONT COLOR=black><FONT SIZE=3>
the largest and smallest elements of a sequence. <CODE>min_max</CODE>
</FONT></FONT><A NAME="@default1061"></A><FONT COLOR=black><FONT SIZE=3>
computes both and returns a tuple of two values.
</FONT></FONT><A NAME="@default1062"></A><FONT COLOR=black><FONT SIZE=3>
 
</FONT></FONT><A NAME="@default1063"></A></P><H2 CLASS="section"><A NAME="toc133"></A><A NAME="htoc147"><FONT COLOR=black><FONT SIZE=3>12.4</FONT></FONT></A><FONT COLOR=black><FONT SIZE=3>&#XA0;&#XA0;Variable-length argument tuples</FONT></FONT></H2><P><A NAME="@default1064"></A><FONT COLOR=black><FONT SIZE=3>
 
</FONT></FONT><A NAME="@default1065"></A><FONT COLOR=black><FONT SIZE=3>
 
</FONT></FONT><A NAME="@default1066"></A><FONT COLOR=black><FONT SIZE=3>
 
</FONT></FONT><A NAME="@default1067"></A><FONT COLOR=black><FONT SIZE=3>
 
</FONT></FONT><A NAME="@default1068"></A></P><P><FONT COLOR=black><FONT SIZE=3>Functions can take a variable number of arguments. A parameter
=== 12.4&#XA0;&#XA0;Variable-length argument tuples ===
name that begins with </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>*</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> </FONT></FONT><FONT COLOR=black><FONT SIZE=3><B>gathers</B></FONT></FONT><FONT COLOR=black><FONT SIZE=3> arguments into
 
a tuple. For example, </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>printall</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3>
 
takes any number of arguments and prints them:</FONT></FONT></P><PRE CLASS="verbatim"><FONT COLOR=blue><FONT SIZE=4>def printall(*args):
 
 
 
 
 
Functions can take a variable number of arguments. A parameter
name that begins with <TT>*</TT> '''gathers''' arguments into
a tuple. For example, <TT>printall</TT>
takes any number of arguments and prints them:
<PRE CLASS="verbatim">def printall(*args):
     print args
     print args
</FONT></FONT></PRE><P><FONT COLOR=black><FONT SIZE=3>The gather parameter can have any name you like, but </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>args</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> is
</PRE>
conventional. Here&#X2019;s how the function works:</FONT></FONT></P><PRE CLASS="verbatim"><FONT COLOR=blue><FONT SIZE=4>&gt;&gt;&gt; printall(1, 2.0, '3')
The gather parameter can have any name you like, but <TT>args</TT> is
conventional. Here&#X2019;s how the function works:
<PRE CLASS="verbatim">&gt;&gt;&gt; printall(1, 2.0, '3')
(1, 2.0, '3')
(1, 2.0, '3')
</FONT></FONT></PRE><P><FONT COLOR=black><FONT SIZE=3>You can combine the gather operator with required and positional
</PRE>
arguments:</FONT></FONT></P><PRE CLASS="verbatim"><FONT COLOR=blue><FONT SIZE=4>def pointless(required, optional=0, *args):
You can combine the gather operator with required and positional
arguments:
<PRE CLASS="verbatim">def pointless(required, optional=0, *args):
     print required, optional, args
     print required, optional, args
</FONT></FONT></PRE><P><FONT COLOR=black><FONT SIZE=3>Run this function with 1, 2, 3 and 4 or more arguments and
</PRE>
make sure you understand what it does.</FONT></FONT></P><P><A NAME="@default1069"></A><FONT COLOR=black><FONT SIZE=3>
Run this function with 1, 2, 3 and 4 or more arguments and
</FONT></FONT><A NAME="@default1070"></A></P><P><FONT COLOR=black><FONT SIZE=3>The complement of gather is </FONT></FONT><FONT COLOR=black><FONT SIZE=3><B>scatter</B></FONT></FONT><FONT COLOR=black><FONT SIZE=3>. If you have a
make sure you understand what it does.
 
 
 
 
The complement of gather is '''scatter'''. If you have a
sequence of values and you want to pass it to a function
sequence of values and you want to pass it to a function
as multiple arguments, you can use the </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>*</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> operator.
as multiple arguments, you can use the <TT>*</TT> operator.
For example, </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>divmod</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> takes exactly two arguments; it
For example, <TT>divmod</TT> takes exactly two arguments; it
doesn&#X2019;t work with a tuple:</FONT></FONT></P><P><A NAME="@default1071"></A><FONT COLOR=black><FONT SIZE=3>
doesn&#X2019;t work with a tuple:
</FONT></FONT><A NAME="@default1072"></A></P><PRE CLASS="verbatim"><FONT COLOR=blue><FONT SIZE=4>&gt;&gt;&gt; t = (7, 3)
 
 
 
<PRE CLASS="verbatim">&gt;&gt;&gt; t = (7, 3)
&gt;&gt;&gt; divmod(t)
&gt;&gt;&gt; divmod(t)
TypeError: divmod expected 2 arguments, got 1
TypeError: divmod expected 2 arguments, got 1
</FONT></FONT></PRE><P><FONT COLOR=black><FONT SIZE=3>But if you scatter the tuple, it works:</FONT></FONT></P><PRE CLASS="verbatim"><FONT COLOR=blue><FONT SIZE=4>&gt;&gt;&gt; divmod(*t)
</PRE>
But if you scatter the tuple, it works:
<PRE CLASS="verbatim">&gt;&gt;&gt; divmod(*t)
(2, 1)
(2, 1)
</FONT></FONT></PRE><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>
</PRE><DIV CLASS="theorem">'''Exercise&#XA0;1'''&#XA0;&#XA0;''
Many of the built-in functions use
Many of the built-in functions use
variable-length argument tuples. For example, </EM></FONT></FONT><FONT COLOR=black><FONT SIZE=3><EM><TT>max</TT></EM></FONT></FONT><FONT COLOR=black><FONT SIZE=3><EM>
variable-length argument tuples. For example, ''''<TT>max</TT>''''
and </EM></FONT></FONT><FONT COLOR=black><FONT SIZE=3><EM><TT>min</TT></EM></FONT></FONT><FONT COLOR=black><FONT SIZE=3><EM> can take any number of arguments:</EM></FONT></FONT><P><A NAME="@default1073"></A><FONT COLOR=black><FONT SIZE=3><EM>
and ''''<TT>min</TT>'''' can take any number of arguments:''
</EM></FONT></FONT><A NAME="@default1074"></A><FONT COLOR=black><FONT SIZE=3><EM>
''
</EM></FONT></FONT><A NAME="@default1075"></A><FONT COLOR=black><FONT SIZE=3><EM>
''''
</EM></FONT></FONT><A NAME="@default1076"></A></P><PRE CLASS="verbatim"><EM><FONT COLOR=blue><FONT SIZE=4>&gt;&gt;&gt; max(1,2,3)
''''
''
<PRE CLASS="verbatim">''&gt;&gt;&gt; max(1,2,3)
3
3
</FONT></FONT></EM></PRE><P><EM><FONT COLOR=black><FONT SIZE=3>But </FONT></FONT></EM><EM><FONT COLOR=black><FONT SIZE=3><TT>sum</TT></FONT></FONT></EM><EM><FONT COLOR=black><FONT SIZE=3> does not.</FONT></FONT></EM></P><P><A NAME="@default1077"></A><EM><FONT COLOR=black><FONT SIZE=3>
''</PRE>
</FONT></FONT></EM><A NAME="@default1078"></A></P><PRE CLASS="verbatim"><EM><FONT COLOR=blue><FONT SIZE=4>&gt;&gt;&gt; sum(1,2,3)
''But ''''<TT>sum</TT>'''' does not.''
 
''
''
<PRE CLASS="verbatim">''&gt;&gt;&gt; sum(1,2,3)
TypeError: sum expected at most 2 arguments, got 3
TypeError: sum expected at most 2 arguments, got 3
</FONT></FONT></EM></PRE><P><EM><FONT COLOR=black><FONT SIZE=3>Write a function called </FONT></FONT></EM><EM><FONT COLOR=black><FONT SIZE=3><TT>sumall</TT></FONT></FONT></EM><EM><FONT COLOR=black><FONT SIZE=3> that takes any number
''</PRE>
of arguments and returns their sum.</FONT></FONT></EM></P></DIV><H2 CLASS="section"><A NAME="toc134"></A><A NAME="htoc148"><FONT COLOR=black><FONT SIZE=3>12.5</FONT></FONT></A><FONT COLOR=black><FONT SIZE=3>&#XA0;&#XA0;Lists and tuples</FONT></FONT></H2><P><A NAME="@default1079"></A><FONT COLOR=black><FONT SIZE=3>
''Write a function called ''''<TT>sumall</TT>'''' that takes any number
</FONT></FONT><A NAME="@default1080"></A></P><P><FONT COLOR=black><FONT SIZE=3><TT>zip</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> is a built-in function that takes two or more sequences and
of arguments and returns their sum.''
&#X201C;zips&#X201D; them into a list</FONT></FONT><SUP><A NAME="text25" HREF="#note25"><FONT COLOR=black><FONT SIZE=3>1</FONT></FONT></A></SUP><FONT COLOR=black><FONT SIZE=3> of tuples where each tuple contains one element from each
</DIV>=== 12.5&#XA0;&#XA0;Lists and tuples ===
sequence.</FONT></FONT></P><P><A NAME="@default1081"></A></P><P><FONT COLOR=black><FONT SIZE=3>This example zips a string and a list:</FONT></FONT></P><PRE CLASS="verbatim"><FONT COLOR=blue><FONT SIZE=4>&gt;&gt;&gt; s = 'abc'
 
 
 
 
<TT>zip</TT> is a built-in function that takes two or more sequences and
&#X201C;zips&#X201D; them into a list<SUP>1</SUP> of tuples where each tuple contains one element from each
sequence.
 
This example zips a string and a list:
<PRE CLASS="verbatim">&gt;&gt;&gt; s = 'abc'
&gt;&gt;&gt; t = [0, 1, 2]
&gt;&gt;&gt; t = [0, 1, 2]
&gt;&gt;&gt; zip(s, t)
&gt;&gt;&gt; zip(s, t)
[('a', 0), ('b', 1), ('c', 2)]
[('a', 0), ('b', 1), ('c', 2)]
</FONT></FONT></PRE><P><FONT COLOR=black><FONT SIZE=3>The result is a list of tuples where each tuple contains
</PRE>
The result is a list of tuples where each tuple contains
a character from the string and the corresponding element from
a character from the string and the corresponding element from
the list.</FONT></FONT></P><P><A NAME="@default1082"></A></P><P><FONT COLOR=black><FONT SIZE=3>If the sequences are not the same length, the result has the
the list.
length of the shorter one.</FONT></FONT></P><PRE CLASS="verbatim"><FONT COLOR=blue><FONT SIZE=4>&gt;&gt;&gt; zip('Anne', 'Elk')
 
If the sequences are not the same length, the result has the
length of the shorter one.
<PRE CLASS="verbatim">&gt;&gt;&gt; zip('Anne', 'Elk')
[('A', 'E'), ('n', 'l'), ('n', 'k')]
[('A', 'E'), ('n', 'l'), ('n', 'k')]
</FONT></FONT></PRE><P><FONT COLOR=black><FONT SIZE=3>You can use tuple assignment in a </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>for</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> loop to traverse a list of
</PRE>
tuples:</FONT></FONT></P><P><A NAME="@default1083"></A><FONT COLOR=black><FONT SIZE=3>
You can use tuple assignment in a <TT>for</TT> loop to traverse a list of
</FONT></FONT><A NAME="@default1084"></A><FONT COLOR=black><FONT SIZE=3>
tuples:
</FONT></FONT><A NAME="@default1085"></A></P><PRE CLASS="verbatim"><FONT COLOR=blue><FONT SIZE=4>t = [('a', 0), ('b', 1), ('c', 2)]
 
 
 
 
<PRE CLASS="verbatim">t = [('a', 0), ('b', 1), ('c', 2)]
for letter, number in t:
for letter, number in t:
     print number, letter
     print number, letter
</FONT></FONT></PRE><P><FONT COLOR=black><FONT SIZE=3>Each time through the loop, Python selects the next tuple in
</PRE>
the list and assigns the elements to </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>letter</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> and  
Each time through the loop, Python selects the next tuple in
</FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>number</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3>. The output of this loop is:</FONT></FONT></P><P><A NAME="@default1086"></A></P><PRE CLASS="verbatim"><FONT COLOR=blue><FONT SIZE=4>0 a
the list and assigns the elements to <TT>letter</TT> and  
<TT>number</TT>. The output of this loop is:
 
<PRE CLASS="verbatim">0 a
1 b
1 b
2 c
2 c
</FONT></FONT></PRE><P><FONT COLOR=black><FONT SIZE=3>If you combine </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>zip</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3>, </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>for</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> and tuple assignment, you get a
</PRE>
If you combine <TT>zip</TT>, <TT>for</TT> and tuple assignment, you get a
useful idiom for traversing two (or more) sequences at the same
useful idiom for traversing two (or more) sequences at the same
time. For example, </FONT></FONT><CODE><FONT COLOR=black><FONT SIZE=3>has_match</FONT></FONT></CODE><FONT COLOR=black><FONT SIZE=3> takes two sequences, </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>t1</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> and
time. For example, <CODE>has_match</CODE> takes two sequences, <TT>t1</TT> and
</FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>t2</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3>, and returns </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>True</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> if there is an index </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>i</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3>
<TT>t2</TT>, and returns <TT>True</TT> if there is an index <TT>i</TT>
such that </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>t1[i] == t2[i]</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3>:</FONT></FONT></P><P><A NAME="@default1087"></A></P><PRE CLASS="verbatim"><FONT COLOR=blue><FONT SIZE=4>def has_match(t1, t2):
such that <TT>t1[i] == t2[i]</TT>:
 
<PRE CLASS="verbatim">def has_match(t1, t2):
     for x, y in zip(t1, t2):
     for x, y in zip(t1, t2):
         if x == y:
         if x == y:
             return True
             return True
     return False
     return False
</FONT></FONT></PRE><P><FONT COLOR=black><FONT SIZE=3>If you need to traverse the elements of a sequence and their
</PRE>
indices, you can use the built-in function </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>enumerate</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3>:</FONT></FONT></P><P><A NAME="@default1088"></A><FONT COLOR=black><FONT SIZE=3>
If you need to traverse the elements of a sequence and their
</FONT></FONT><A NAME="@default1089"></A><FONT COLOR=black><FONT SIZE=3>
indices, you can use the built-in function <TT>enumerate</TT>:
</FONT></FONT><A NAME="@default1090"></A></P><PRE CLASS="verbatim"><FONT COLOR=blue><FONT SIZE=4>for index, element in enumerate('abc'):
 
 
 
 
<PRE CLASS="verbatim">for index, element in enumerate('abc'):
     print index, element
     print index, element
</FONT></FONT></PRE><P><FONT COLOR=black><FONT SIZE=3>The output of this loop is:</FONT></FONT></P><PRE CLASS="verbatim"><FONT COLOR=blue><FONT SIZE=4>0 a
</PRE>
The output of this loop is:
<PRE CLASS="verbatim">0 a
1 b
1 b
2 c
2 c
</FONT></FONT></PRE><P><FONT COLOR=black><FONT SIZE=3>Again.</FONT></FONT></P><H2 CLASS="section"><A NAME="toc135"></A><A NAME="htoc149"><FONT COLOR=black><FONT SIZE=3>12.6</FONT></FONT></A><FONT COLOR=black><FONT SIZE=3>&#XA0;&#XA0;Dictionaries and tuples</FONT></FONT></H2><P><A NAME="@default1091"></A><FONT COLOR=black><FONT SIZE=3>
</PRE>
</FONT></FONT><A NAME="@default1092"></A><FONT COLOR=black><FONT SIZE=3>
Again.
</FONT></FONT><A NAME="@default1093"></A><FONT COLOR=black><FONT SIZE=3>
=== 12.6&#XA0;&#XA0;Dictionaries and tuples ===
</FONT></FONT><A NAME="@default1094"></A></P><P><FONT COLOR=black><FONT SIZE=3>Dictionaries have a method called </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>items</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> that returns a list of
 
tuples, where each tuple is a key-value pair</FONT></FONT><SUP><A NAME="text26" HREF="#note26"><FONT COLOR=black><FONT SIZE=3>2</FONT></FONT></A></SUP><FONT COLOR=black><FONT SIZE=3>.</FONT></FONT></P><PRE CLASS="verbatim"><FONT COLOR=blue><FONT SIZE=4>&gt;&gt;&gt; d = {'a':0, 'b':1, 'c':2}
 
 
 
 
 
Dictionaries have a method called <TT>items</TT> that returns a list of
tuples, where each tuple is a key-value pair<SUP>2</SUP>.
<PRE CLASS="verbatim">&gt;&gt;&gt; d = {'a':0, 'b':1, 'c':2}
&gt;&gt;&gt; t = d.items()
&gt;&gt;&gt; t = d.items()
&gt;&gt;&gt; print t
&gt;&gt;&gt; print t
[('a', 0), ('c', 2), ('b', 1)]
[('a', 0), ('c', 2), ('b', 1)]
</FONT></FONT></PRE><P><FONT COLOR=black><FONT SIZE=3>As you should expect from a dictionary, the items are in no
</PRE>
particular order.</FONT></FONT></P><P><A NAME="@default1095"></A></P><P><FONT COLOR=black><FONT SIZE=3>Conversely, you can use a list of tuples to initialize
As you should expect from a dictionary, the items are in no
a new dictionary:</FONT></FONT></P><PRE CLASS="verbatim"><FONT COLOR=blue><FONT SIZE=4>&gt;&gt;&gt; t = [('a', 0), ('c', 2), ('b', 1)]
particular order.
 
Conversely, you can use a list of tuples to initialize
a new dictionary:
<PRE CLASS="verbatim">&gt;&gt;&gt; t = [('a', 0), ('c', 2), ('b', 1)]
&gt;&gt;&gt; d = dict(t)
&gt;&gt;&gt; d = dict(t)
&gt;&gt;&gt; print d
&gt;&gt;&gt; print d
{'a': 0, 'c': 2, 'b': 1}
{'a': 0, 'c': 2, 'b': 1}
</FONT></FONT></PRE><P><FONT COLOR=black><FONT SIZE=3>Combining </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>dict</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> with </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>zip</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> yields a concise way
</PRE>
to create a dictionary:</FONT></FONT></P><P><A NAME="@default1096"></A></P><PRE CLASS="verbatim"><FONT COLOR=blue><FONT SIZE=4>&gt;&gt;&gt; d = dict(zip('abc', range(3)))
Combining <TT>dict</TT> with <TT>zip</TT> yields a concise way
to create a dictionary:
 
<PRE CLASS="verbatim">&gt;&gt;&gt; d = dict(zip('abc', range(3)))
&gt;&gt;&gt; print d
&gt;&gt;&gt; print d
{'a': 0, 'c': 2, 'b': 1}
{'a': 0, 'c': 2, 'b': 1}
</FONT></FONT></PRE><P><FONT COLOR=black><FONT SIZE=3>The dictionary method </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>update</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> also takes a list of tuples
</PRE>
and adds them, as key-value pairs, to an existing dictionary.</FONT></FONT></P><P><A NAME="@default1097"></A><FONT COLOR=black><FONT SIZE=3>
The dictionary method <TT>update</TT> also takes a list of tuples
</FONT></FONT><A NAME="@default1098"></A></P><P><A NAME="@default1099"></A><FONT COLOR=black><FONT SIZE=3>
and adds them, as key-value pairs, to an existing dictionary.
</FONT></FONT><A NAME="@default1100"></A></P><P><FONT COLOR=black><FONT SIZE=3>Combining </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>items</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3>, tuple assignment and </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>for</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3>, you
 
get the idiom for traversing the keys and values of a dictionary:</FONT></FONT></P><PRE CLASS="verbatim"><FONT COLOR=blue><FONT SIZE=4>for key, val in d.items():
 
 
 
 
 
 
Combining <TT>items</TT>, tuple assignment and <TT>for</TT>, you
get the idiom for traversing the keys and values of a dictionary:
<PRE CLASS="verbatim">for key, val in d.items():
     print val, key
     print val, key
</FONT></FONT></PRE><P><FONT COLOR=black><FONT SIZE=3>The output of this loop is:</FONT></FONT></P><PRE CLASS="verbatim"><FONT COLOR=blue><FONT SIZE=4>0 a
</PRE>
The output of this loop is:
<PRE CLASS="verbatim">0 a
2 c
2 c
1 b
1 b
</FONT></FONT></PRE><P><FONT COLOR=black><FONT SIZE=3>Again.</FONT></FONT></P><P><A NAME="@default1101"></A><FONT COLOR=black><FONT SIZE=3>
</PRE>
</FONT></FONT><A NAME="@default1102"></A></P><P><FONT COLOR=black><FONT SIZE=3>It is common to use tuples as keys in dictionaries (primarily because
Again.
 
 
 
 
It is common to use tuples as keys in dictionaries (primarily because
you can&#X2019;t use lists). For example, a telephone directory might map
you can&#X2019;t use lists). For example, a telephone directory might map
from last-name, first-name pairs to telephone numbers. Assuming
from last-name, first-name pairs to telephone numbers. Assuming
that we have defined </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>last</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3>, </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>first</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> and </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>number</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3>, we
that we have defined <TT>last</TT>, <TT>first</TT> and <TT>number</TT>, we
could write:</FONT></FONT></P><PRE CLASS="verbatim"><FONT COLOR=blue><FONT SIZE=4>directory[last,first] = number
could write:
</FONT></FONT></PRE><P><FONT COLOR=black><FONT SIZE=3>The expression in brackets is a tuple. We could use tuple
<PRE CLASS="verbatim">directory[last,first] = number
assignment to traverse this dictionary.</FONT></FONT></P><P><A NAME="@default1103"></A></P><PRE CLASS="verbatim"><FONT COLOR=blue><FONT SIZE=4>for last, first in directory:
</PRE>
The expression in brackets is a tuple. We could use tuple
assignment to traverse this dictionary.
 
<PRE CLASS="verbatim">for last, first in directory:
     print first, last, directory[last,first]
     print first, last, directory[last,first]
</FONT></FONT></PRE><P><FONT COLOR=black><FONT SIZE=3>This loop traverses the keys in </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>directory</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3>, which are tuples. It
</PRE>
assigns the elements of each tuple to </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>last</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> and </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>first</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3>, then
This loop traverses the keys in <TT>directory</TT>, which are tuples. It
prints the name and corresponding telephone number.</FONT></FONT></P><P><FONT COLOR=black><FONT SIZE=3>There are two ways to represent tuples in a state diagram. The more
assigns the elements of each tuple to <TT>last</TT> and <TT>first</TT>, then
prints the name and corresponding telephone number.
 
There are two ways to represent tuples in a state diagram. The more
detailed version shows the indices and elements just as they appear in
detailed version shows the indices and elements just as they appear in
a list. For example, the tuple </FONT></FONT><CODE><FONT COLOR=black><FONT SIZE=3>('Cleese', 'John')</FONT></FONT></CODE><FONT COLOR=black><FONT SIZE=3> would appear:</FONT></FONT></P><P><A NAME="@default1104"></A><FONT COLOR=black><FONT SIZE=3>
a list. For example, the tuple <CODE>('Cleese', 'John')</CODE> would appear:
</FONT></FONT><A NAME="@default1105"></A></P><DIV CLASS="center"><FONT COLOR=black><FONT SIZE=3><IMG SRC="book020.png"></FONT></FONT></DIV><P><FONT COLOR=black><FONT SIZE=3>But in a larger diagram you might want to leave out the
 
 
 
<DIV CLASS="center"><IMG SRC="book020.png"></DIV>
But in a larger diagram you might want to leave out the
details. For example, a diagram of the telephone directory might
details. For example, a diagram of the telephone directory might
appear:</FONT></FONT></P><DIV CLASS="center"><FONT COLOR=black><FONT SIZE=3><IMG SRC="book021.png"></FONT></FONT></DIV><P><FONT COLOR=black><FONT SIZE=3>Here the tuples are shown using Python syntax as a graphical
appear:
shorthand.</FONT></FONT></P><P><FONT COLOR=black><FONT SIZE=3>The telephone number in the diagram is the complaints line for the
<DIV CLASS="center"><IMG SRC="book021.png"></DIV>
BBC, so please don&#X2019;t call it.</FONT></FONT></P><H2 CLASS="section"><A NAME="toc136"></A><A NAME="htoc150"><FONT COLOR=black><FONT SIZE=3>12.7</FONT></FONT></A><FONT COLOR=black><FONT SIZE=3>&#XA0;&#XA0;Comparing tuples</FONT></FONT></H2><P><A NAME="@default1106"></A><FONT COLOR=black><FONT SIZE=3>
Here the tuples are shown using Python syntax as a graphical
</FONT></FONT><A NAME="@default1107"></A><FONT COLOR=black><FONT SIZE=3>
shorthand.
</FONT></FONT><A NAME="@default1108"></A><FONT COLOR=black><FONT SIZE=3>
 
</FONT></FONT><A NAME="@default1109"></A></P><P><FONT COLOR=black><FONT SIZE=3>The comparison operators work with tuples and other sequences;
The telephone number in the diagram is the complaints line for the
BBC, so please don&#X2019;t call it.
=== 12.7&#XA0;&#XA0;Comparing tuples ===
 
 
 
 
 
 
The comparison operators work with tuples and other sequences;
Python starts by comparing the first element from each
Python starts by comparing the first element from each
sequence. If they are equal, it goes on to the next elements,
sequence. If they are equal, it goes on to the next elements,
and so on, until it finds elements that differ. Subsequent
and so on, until it finds elements that differ. Subsequent
elements are not considered (even if they are really big).</FONT></FONT></P><PRE CLASS="verbatim"><FONT COLOR=blue><FONT SIZE=4>&gt;&gt;&gt; (0, 1, 2) &lt; (0, 3, 4)
elements are not considered (even if they are really big).
<PRE CLASS="verbatim">&gt;&gt;&gt; (0, 1, 2) &lt; (0, 3, 4)
True
True
&gt;&gt;&gt; (0, 1, 2000000) &lt; (0, 3, 4)
&gt;&gt;&gt; (0, 1, 2000000) &lt; (0, 3, 4)
True
True
</FONT></FONT></PRE><P><FONT COLOR=black><FONT SIZE=3>The </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>sort</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> function works the same way. It sorts  
</PRE>
The <TT>sort</TT> function works the same way. It sorts  
primarily by first element, but in the case of a tie, it sorts
primarily by first element, but in the case of a tie, it sorts
by second element, and so on. </FONT></FONT></P><P><FONT COLOR=black><FONT SIZE=3>This feature lends itself to a pattern called </FONT></FONT><FONT COLOR=black><FONT SIZE=3><B>DSU</B></FONT></FONT><FONT COLOR=black><FONT SIZE=3> for </FONT></FONT></P><DL CLASS="description"><DT CLASS="dt-description"><FONT COLOR=black><FONT SIZE=3><B>Decorate</B></FONT></FONT></DT><DD CLASS="dd-description"><FONT COLOR=black><FONT SIZE=3> a sequence by building a list of tuples
by second element, and so on.  
with one or more sort keys preceding the elements from the sequence,</FONT></FONT></DD><DT CLASS="dt-description"><FONT COLOR=black><FONT SIZE=3><B>Sort</B></FONT></FONT></DT><DD CLASS="dd-description"><FONT COLOR=black><FONT SIZE=3> the list of tuples, and</FONT></FONT></DD><DT CLASS="dt-description"><FONT COLOR=black><FONT SIZE=3><B>Undecorate</B></FONT></FONT></DT><DD CLASS="dd-description"><FONT COLOR=black><FONT SIZE=3> by extracting the sorted elements of the sequence.</FONT></FONT></DD></DL><P><A NAME="DSU"></A><FONT COLOR=black><FONT SIZE=3>
 
</FONT></FONT><A NAME="@default1110"></A><FONT COLOR=black><FONT SIZE=3>
This feature lends itself to a pattern called '''DSU''' for  
</FONT></FONT><A NAME="@default1111"></A><FONT COLOR=black><FONT SIZE=3>
<DL CLASS="description"><DT CLASS="dt-description">'''Decorate'''</DT><DD CLASS="dd-description"> a sequence by building a list of tuples
</FONT></FONT><A NAME="@default1112"></A><FONT COLOR=black><FONT SIZE=3>
with one or more sort keys preceding the elements from the sequence,</DD><DT CLASS="dt-description">'''Sort'''</DT><DD CLASS="dd-description"> the list of tuples, and</DD><DT CLASS="dt-description">'''Undecorate'''</DT><DD CLASS="dd-description"> by extracting the sorted elements of the sequence.</DD></DL>
</FONT></FONT><A NAME="@default1113"></A></P><P><FONT COLOR=black><FONT SIZE=3>For example, suppose you have a list of words and you want to
 
sort them from longest to shortest:</FONT></FONT></P><PRE CLASS="verbatim"><FONT COLOR=blue><FONT SIZE=4>def sort_by_length(words):
 
 
 
 
 
For example, suppose you have a list of words and you want to
sort them from longest to shortest:
<PRE CLASS="verbatim">def sort_by_length(words):
     t = []
     t = []
     for word in words:
     for word in words:
Line 271: Line 451:
         res.append(word)
         res.append(word)
     return res
     return res
</FONT></FONT></PRE><P><FONT COLOR=black><FONT SIZE=3>The first loop builds a list of tuples, where each
</PRE>
tuple is a word preceded by its length.</FONT></FONT></P><P><FONT COLOR=black><FONT SIZE=3><TT>sort</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> compares the first element, length, first, and
The first loop builds a list of tuples, where each
tuple is a word preceded by its length.
 
<TT>sort</TT> compares the first element, length, first, and
only considers the second element to break ties. The keyword argument
only considers the second element to break ties. The keyword argument
</FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>reverse=True</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> tells </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>sort</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> to go in decreasing order.</FONT></FONT></P><P><A NAME="@default1114"></A><FONT COLOR=black><FONT SIZE=3>
<TT>reverse=True</TT> tells <TT>sort</TT> to go in decreasing order.
</FONT></FONT><A NAME="@default1115"></A><FONT COLOR=black><FONT SIZE=3>
 
</FONT></FONT><A NAME="@default1116"></A></P><P><FONT COLOR=black><FONT SIZE=3>The second loop traverses the list of tuples and builds a list of
 
words in descending order of length.</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;<EM>
 
 
 
The second loop traverses the list of tuples and builds a list of
words in descending order of length.
<DIV CLASS="theorem">'''Exercise&#XA0;2'''&#XA0;&#XA0;''
In this example, ties are broken by comparing words, so words
In this example, ties are broken by comparing words, so words
with the same length appear in alphabetical order. For other
with the same length appear in alphabetical order. For other
applications you might want to break ties at random. Modify
applications you might want to break ties at random. Modify
this example so that words with the same length appear in
this example so that words with the same length appear in
random order. Hint: see the </EM></FONT></FONT><FONT COLOR=black><FONT SIZE=3><EM><TT>random</TT></EM></FONT></FONT><FONT COLOR=black><FONT SIZE=3><EM> function in the
random order. Hint: see the ''''<TT>random</TT>'''' function in the
</EM></FONT></FONT><FONT COLOR=black><FONT SIZE=3><EM><TT>random</TT></EM></FONT></FONT><FONT COLOR=black><FONT SIZE=3><EM> module.</EM></FONT></FONT><P><A NAME="@default1117"></A><FONT COLOR=black><FONT SIZE=3><EM>
''''<TT>random</TT>'''' module.''
</EM></FONT></FONT><A NAME="@default1118"></A><FONT COLOR=black><FONT SIZE=3><EM>
''
</EM></FONT></FONT><A NAME="@default1119"></A><FONT COLOR=black><FONT SIZE=3><EM>
''''
</EM></FONT></FONT><A NAME="@default1120"></A></P></DIV><H2 CLASS="section"><A NAME="toc137"></A><A NAME="htoc151"><FONT COLOR=black><FONT SIZE=3>12.8</FONT></FONT></A><FONT COLOR=black><FONT SIZE=3>&#XA0;&#XA0;Sequences of sequences</FONT></FONT></H2><P><FONT COLOR=black><FONT SIZE=3>
''''
</FONT></FONT><A NAME="@default1121"></A></P><P><FONT COLOR=black><FONT SIZE=3>I have focused on lists of tuples, but almost all of the examples in
''
</DIV>=== 12.8&#XA0;&#XA0;Sequences of sequences ===
 
 
 
 
I have focused on lists of tuples, but almost all of the examples in
this chapter also work with lists of lists, tuples of tuples, and
this chapter also work with lists of lists, tuples of tuples, and
tuples of lists. To avoid enumerating the possible combinations, it
tuples of lists. To avoid enumerating the possible combinations, it
is sometimes easier to talk about sequences of sequences.</FONT></FONT></P><P><FONT COLOR=black><FONT SIZE=3>In many contexts, the different kinds of sequences (strings, lists and
is sometimes easier to talk about sequences of sequences.
 
In many contexts, the different kinds of sequences (strings, lists and
tuples) can be used interchangeably. So how and why do you choose one
tuples) can be used interchangeably. So how and why do you choose one
over the others?</FONT></FONT></P><P><A NAME="@default1122"></A><FONT COLOR=black><FONT SIZE=3>
over the others?
</FONT></FONT><A NAME="@default1123"></A><FONT COLOR=black><FONT SIZE=3>
 
</FONT></FONT><A NAME="@default1124"></A><FONT COLOR=black><FONT SIZE=3>
 
</FONT></FONT><A NAME="@default1125"></A><FONT COLOR=black><FONT SIZE=3>
 
</FONT></FONT><A NAME="@default1126"></A></P><P><FONT COLOR=black><FONT SIZE=3>To start with the obvious, strings are more limited than other
 
 
 
 
To start with the obvious, strings are more limited than other
sequences because the elements have to be characters. They are
sequences because the elements have to be characters. They are
also immutable. If you need the ability to change the characters
also immutable. If you need the ability to change the characters
in a string (as opposed to creating a new string), you might
in a string (as opposed to creating a new string), you might
want to use a list of characters instead.</FONT></FONT></P><P><FONT COLOR=black><FONT SIZE=3>Lists are more common than tuples, mostly because they are mutable.
want to use a list of characters instead.
But there are a few cases where you might prefer tuples:</FONT></FONT></P><OL CLASS="enumerate" type=1><LI CLASS="li-enumerate"><FONT COLOR=black><FONT SIZE=3>In some contexts, like a </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>return</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> statement, it is
 
Lists are more common than tuples, mostly because they are mutable.
But there are a few cases where you might prefer tuples:
 
*In some contexts, like a <TT>return</TT> statement, it is
syntactically simpler to create a tuple than a list. In other
syntactically simpler to create a tuple than a list. In other
contexts, you might prefer a list.</FONT></FONT></LI><LI CLASS="li-enumerate"><FONT COLOR=black><FONT SIZE=3>If you want to use a sequence as a dictionary key, you
contexts, you might prefer a list.
have to use an immutable type like a tuple or string.</FONT></FONT></LI><LI CLASS="li-enumerate"><FONT COLOR=black><FONT SIZE=3>If you are passing a sequence as an argument to a function,
 
*If you want to use a sequence as a dictionary key, you
have to use an immutable type like a tuple or string.
 
*If you are passing a sequence as an argument to a function,
using tuples reduces the potential for unexpected behavior
using tuples reduces the potential for unexpected behavior
due to aliasing.</FONT></FONT></LI></OL><P><FONT COLOR=black><FONT SIZE=3>Because tuples are immutable, they don&#X2019;t provide methods
due to aliasing.
like </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>sort</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> and </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>reverse</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3>, which modify existing lists.
 
But Python provides the built-in functions </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>sorted</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3>
Because tuples are immutable, they don&#X2019;t provide methods
and </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>reversed</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3>, which take any sequence as a parameter
like <TT>sort</TT> and <TT>reverse</TT>, which modify existing lists.
But Python provides the built-in functions <TT>sorted</TT>
and <TT>reversed</TT>, which take any sequence as a parameter
and return a new list with the same elements in a different
and return a new list with the same elements in a different
order.</FONT></FONT></P><P><A NAME="@default1127"></A><FONT COLOR=black><FONT SIZE=3>
order.
</FONT></FONT><A NAME="@default1128"></A><FONT COLOR=black><FONT SIZE=3>
 
</FONT></FONT><A NAME="@default1129"></A><FONT COLOR=black><FONT SIZE=3>
 
</FONT></FONT><A NAME="@default1130"></A></P><H2 CLASS="section"><A NAME="toc138"></A><A NAME="htoc152"><FONT COLOR=black><FONT SIZE=3>12.9</FONT></FONT></A><FONT COLOR=black><FONT SIZE=3>&#XA0;&#XA0;Debugging</FONT></FONT></H2><P><A NAME="@default1131"></A><FONT COLOR=black><FONT SIZE=3>
 
</FONT></FONT><A NAME="@default1132"></A><FONT COLOR=black><FONT SIZE=3>
 
</FONT></FONT><A NAME="@default1133"></A><FONT COLOR=black><FONT SIZE=3>
 
</FONT></FONT><A NAME="@default1134"></A></P><P><FONT COLOR=black><FONT SIZE=3>Lists, dictionaries and tuples are known generically as </FONT></FONT><FONT COLOR=black><FONT SIZE=3><B>data
=== 12.9&#XA0;&#XA0;Debugging ===
structures</B></FONT></FONT><FONT COLOR=black><FONT SIZE=3>; in this chapter we are starting to see compound data
 
 
 
 
 
 
Lists, dictionaries and tuples are known generically as '''data
structures'''; in this chapter we are starting to see compound data
structures, like lists of tuples, and dictionaries that contain tuples
structures, like lists of tuples, and dictionaries that contain tuples
as keys and lists as values. Compound data structures are useful, but
as keys and lists as values. Compound data structures are useful, but
they are prone to what I call </FONT></FONT><FONT COLOR=black><FONT SIZE=3><B>shape errors</B></FONT></FONT><FONT COLOR=black><FONT SIZE=3>; that is, errors
they are prone to what I call '''shape errors'''; that is, errors
caused when a data structure has the wrong type, size or composition.
caused when a data structure has the wrong type, size or composition.
For example, if you are expecting a list with one integer and I
For example, if you are expecting a list with one integer and I
give you a plain old integer (not in a list), it won&#X2019;t work.</FONT></FONT></P><P><A NAME="@default1135"></A><FONT COLOR=black><FONT SIZE=3>
give you a plain old integer (not in a list), it won&#X2019;t work.
</FONT></FONT><A NAME="@default1136"></A></P><P><FONT COLOR=black><FONT SIZE=3>To help debug these kinds of errors, I have written a module
 
called </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>structshape</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> that provides a function, also called
 
</FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>structshape</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3>, that takes any kind of data structure as
 
 
To help debug these kinds of errors, I have written a module
called <TT>structshape</TT> that provides a function, also called
<TT>structshape</TT>, that takes any kind of data structure as
an argument and returns a string that summarizes its shape.
an argument and returns a string that summarizes its shape.
You can download it from </FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>thinkpython.com/code/structshape.py</TT></FONT></FONT></P><P><FONT COLOR=black><FONT SIZE=3>Here&#X2019;s the result for a simple list:</FONT></FONT></P><PRE CLASS="verbatim"><FONT COLOR=blue><FONT SIZE=4>&gt;&gt;&gt; from structshape import structshape
You can download it from <TT>thinkpython.com/code/structshape.py</TT>
 
Here&#X2019;s the result for a simple list:
<PRE CLASS="verbatim">&gt;&gt;&gt; from structshape import structshape
&gt;&gt;&gt; t = [1,2,3]
&gt;&gt;&gt; t = [1,2,3]
&gt;&gt;&gt; print structshape(t)
&gt;&gt;&gt; print structshape(t)
list of 3 int
list of 3 int
</FONT></FONT></PRE><P><FONT COLOR=black><FONT SIZE=3>A fancier program might write &#X201C;list of 3 int</FONT></FONT><FONT COLOR=black><FONT SIZE=3><EM>s</EM></FONT></FONT><FONT COLOR=black><FONT SIZE=3>,&#X201D; but it
</PRE>
was easier not to deal with plurals. Here&#X2019;s a list of lists:</FONT></FONT></P><PRE CLASS="verbatim"><FONT COLOR=blue><FONT SIZE=4>&gt;&gt;&gt; t2 = [[1,2], [3,4], [5,6]]
A fancier program might write &#X201C;list of 3 int''s'',&#X201D; but it
was easier not to deal with plurals. Here&#X2019;s a list of lists:
<PRE CLASS="verbatim">&gt;&gt;&gt; t2 = [[1,2], [3,4], [5,6]]
&gt;&gt;&gt; print structshape(t2)
&gt;&gt;&gt; print structshape(t2)
list of 3 list of 2 int
list of 3 list of 2 int
</FONT></FONT></PRE><P><FONT COLOR=black><FONT SIZE=3>If the elements of the list are not the same type,
</PRE>
</FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>structshape</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> groups them, in order, by type:</FONT></FONT></P><PRE CLASS="verbatim"><FONT COLOR=blue><FONT SIZE=4>&gt;&gt;&gt; t3 = [1, 2, 3, 4.0, '5', '6', [7], [8], 9]
If the elements of the list are not the same type,
<TT>structshape</TT> groups them, in order, by type:
<PRE CLASS="verbatim">&gt;&gt;&gt; t3 = [1, 2, 3, 4.0, '5', '6', [7], [8], 9]
&gt;&gt;&gt; print structshape(t3)
&gt;&gt;&gt; print structshape(t3)
list of (3 int, float, 2 str, 2 list of int, int)
list of (3 int, float, 2 str, 2 list of int, int)
</FONT></FONT></PRE><P><FONT COLOR=black><FONT SIZE=3>Here&#X2019;s a list of tuples:</FONT></FONT></P><PRE CLASS="verbatim"><FONT COLOR=blue><FONT SIZE=4>&gt;&gt;&gt; s = 'abc'
</PRE>
Here&#X2019;s a list of tuples:
<PRE CLASS="verbatim">&gt;&gt;&gt; s = 'abc'
&gt;&gt;&gt; lt = zip(t, s)
&gt;&gt;&gt; lt = zip(t, s)
&gt;&gt;&gt; print structshape(lt)
&gt;&gt;&gt; print structshape(lt)
list of 3 tuple of (int, str)
list of 3 tuple of (int, str)
</FONT></FONT></PRE><P><FONT COLOR=black><FONT SIZE=3>And here&#X2019;s a dictionary with 3 items that map integers to strings.</FONT></FONT></P><PRE CLASS="verbatim"><FONT COLOR=blue><FONT SIZE=4>&gt;&gt;&gt; d = dict(lt)  
</PRE>
And here&#X2019;s a dictionary with 3 items that map integers to strings.
<PRE CLASS="verbatim">&gt;&gt;&gt; d = dict(lt)  
&gt;&gt;&gt; print structshape(d)
&gt;&gt;&gt; print structshape(d)
dict of 3 int-&gt;str
dict of 3 int-&gt;str
</FONT></FONT></PRE><P><FONT COLOR=black><FONT SIZE=3>If you are having trouble keeping track of your data structures,
</PRE>
</FONT></FONT><FONT COLOR=black><FONT SIZE=3><TT>structshape</TT></FONT></FONT><FONT COLOR=black><FONT SIZE=3> can help.</FONT></FONT></P><H2 CLASS="section"><A NAME="toc139"></A><A NAME="htoc153"><FONT COLOR=black><FONT SIZE=3>12.10</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>tuple:</B></FONT></FONT></DT><DD CLASS="dd-description"><FONT COLOR=black><FONT SIZE=3> An immutable sequence of elements.
If you are having trouble keeping track of your data structures,
</FONT></FONT><A NAME="@default1137"></A></DD><DT CLASS="dt-description"><FONT COLOR=black><FONT SIZE=3><B>tuple assignment:</B></FONT></FONT></DT><DD CLASS="dd-description"><FONT COLOR=black><FONT SIZE=3> An assignment with a sequence on the
<TT>structshape</TT> can help.
=== 12.10&#XA0;&#XA0;Glossary ===
 
<DL CLASS="description"><DT CLASS="dt-description">'''tuple:'''</DT><DD CLASS="dd-description"> An immutable sequence of elements.
</DD><DT CLASS="dt-description">'''tuple assignment:'''</DT><DD CLASS="dd-description"> An assignment with a sequence on the
right side and a tuple of variables on the left. The right
right side and a tuple of variables on the left. The right
side is evaluated and then its elements are assigned to the
side is evaluated and then its elements are assigned to the
variables on the left.
variables on the left.
</FONT></FONT><A NAME="@default1138"></A><FONT COLOR=black><FONT SIZE=3>
 
</FONT></FONT><A NAME="@default1139"></A></DD><DT CLASS="dt-description"><FONT COLOR=black><FONT SIZE=3><B>gather:</B></FONT></FONT></DT><DD CLASS="dd-description"><FONT COLOR=black><FONT SIZE=3> The operation of assembling a variable-length
</DD><DT CLASS="dt-description">'''gather:'''</DT><DD CLASS="dd-description"> The operation of assembling a variable-length
argument tuple.
argument tuple.
</FONT></FONT><A NAME="@default1140"></A></DD><DT CLASS="dt-description"><FONT COLOR=black><FONT SIZE=3><B>scatter:</B></FONT></FONT></DT><DD CLASS="dd-description"><FONT COLOR=black><FONT SIZE=3> The operation of treating a sequence as a list of
</DD><DT CLASS="dt-description">'''scatter:'''</DT><DD CLASS="dd-description"> The operation of treating a sequence as a list of
arguments.
arguments.
</FONT></FONT><A NAME="@default1141"></A></DD><DT CLASS="dt-description"><FONT COLOR=black><FONT SIZE=3><B>DSU:</B></FONT></FONT></DT><DD CLASS="dd-description"><FONT COLOR=black><FONT SIZE=3> Abbreviation of &#X201C;decorate-sort-undecorate,&#X201D; a
</DD><DT CLASS="dt-description">'''DSU:'''</DT><DD CLASS="dd-description"> Abbreviation of &#X201C;decorate-sort-undecorate,&#X201D; a
pattern that involves building a list of tuples, sorting, and
pattern that involves building a list of tuples, sorting, and
extracting part of the result.
extracting part of the result.
</FONT></FONT><A NAME="@default1142"></A></DD><DT CLASS="dt-description"><FONT COLOR=black><FONT SIZE=3><B>data structure:</B></FONT></FONT></DT><DD CLASS="dd-description"><FONT COLOR=black><FONT SIZE=3> A collection of related values, often
</DD><DT CLASS="dt-description">'''data structure:'''</DT><DD CLASS="dd-description"> A collection of related values, often
organized in lists, dictionaries, tuples, etc.
organized in lists, dictionaries, tuples, etc.
</FONT></FONT><A NAME="@default1143"></A></DD><DT CLASS="dt-description"><FONT COLOR=black><FONT SIZE=3><B>shape (of a data structure):</B></FONT></FONT></DT><DD CLASS="dd-description"><FONT COLOR=black><FONT SIZE=3> A summary of the type,
</DD><DT CLASS="dt-description">'''shape (of a data structure):'''</DT><DD CLASS="dd-description"> A summary of the type,
size and composition of a data structure.
size and composition of a data structure.
</FONT></FONT><A NAME="@default1144"></A></DD></DL><H2 CLASS="section"><A NAME="toc140"></A><A NAME="htoc154"><FONT COLOR=black><FONT SIZE=3>12.11</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;3</B></FONT></FONT><FONT COLOR=black><FONT SIZE=3>&#XA0;&#XA0;<EM>
</DD></DL>=== 12.11&#XA0;&#XA0;Exercises ===
Write a function called </EM></FONT></FONT><CODE><FONT COLOR=black><FONT SIZE=3><EM>most_frequent</EM></FONT></FONT></CODE><FONT COLOR=black><FONT SIZE=3><EM> that takes a string and
 
<DIV CLASS="theorem">'''Exercise&#XA0;3'''&#XA0;&#XA0;''
Write a function called ''<CODE>''most_frequent''</CODE>'' that takes a string and
prints the letters in decreasing order of frequency. Find text
prints the letters in decreasing order of frequency. Find text
samples from several different languages and see how letter frequency
samples from several different languages and see how letter frequency
varies between languages. Compare your results with the tables at
varies between languages. Compare your results with the tables at
</EM></FONT></FONT><FONT COLOR=black><FONT SIZE=3><EM><TT>wikipedia.org/wiki/Letter_frequencies</TT></EM></FONT></FONT><FONT COLOR=black><FONT SIZE=3><EM>.</EM></FONT></FONT><P><A NAME="@default1145"></A><FONT COLOR=black><FONT SIZE=3><EM>
''''<TT>wikipedia.org/wiki/Letter_frequencies</TT>''''.''
</EM></FONT></FONT><A NAME="@default1146"></A></P></DIV><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>
''
</EM></FONT></FONT><A NAME="anagrams"></A><P><A NAME="@default1147"></A><FONT COLOR=black><FONT SIZE=3><EM>
''
</EM></FONT></FONT><A NAME="@default1148"></A></P><P><FONT COLOR=black><FONT SIZE=3><EM>More anagrams!</EM></FONT></FONT></P><OL CLASS="enumerate" type=1><LI CLASS="li-enumerate"><FONT COLOR=black><FONT SIZE=3><EM>Write a program
</DIV><DIV CLASS="theorem">'''Exercise&#XA0;4'''&#XA0;&#XA0;''
that reads a word list from a file (see Section&#XA0;</EM></FONT></FONT><A HREF="book010.html#wordlist"><FONT COLOR=black><FONT SIZE=3><EM>9.1</EM></FONT></FONT></A><FONT COLOR=black><FONT SIZE=3><EM>) and
''
prints all the sets of words that are anagrams.</EM></FONT></FONT><P><FONT COLOR=black><FONT SIZE=3><EM>Here is an example of what the output might look like:</EM></FONT></FONT></P><PRE CLASS="verbatim"><EM><FONT COLOR=blue><FONT SIZE=4>['deltas', 'desalt', 'lasted', 'salted', 'slated', 'staled']
''
''
 
''More anagrams!''
 
*''Write a program
that reads a word list from a file (see Section&#XA0;''''9.1'''') and
prints all the sets of words that are anagrams.''
''Here is an example of what the output might look like:''
<PRE CLASS="verbatim">''['deltas', 'desalt', 'lasted', 'salted', 'slated', 'staled']
['retainers', 'ternaries']
['retainers', 'ternaries']
['generating', 'greatening']
['generating', 'greatening']
['resmelts', 'smelters', 'termless']
['resmelts', 'smelters', 'termless']
</FONT></FONT></EM></PRE><P><EM><FONT COLOR=black><FONT SIZE=3>Hint: you might want to build a dictionary that maps from a
''</PRE>
''Hint: you might want to build a dictionary that maps from a
set of letters to a list of words that can be spelled with those
set of letters to a list of words that can be spelled with those
letters. The question is, how can you represent the set of
letters. The question is, how can you represent the set of
letters in a way that can be used as a key?</FONT></FONT></EM></P></LI><LI CLASS="li-enumerate"><EM><FONT COLOR=black><FONT SIZE=3>Modify the previous program so that it prints the largest set
letters in a way that can be used as a key?''
of anagrams first, followed by the second largest set, and so on.</FONT></FONT></EM><P><A NAME="@default1149"></A><EM><FONT COLOR=black><FONT SIZE=3>
 
</FONT></FONT></EM><A NAME="@default1150"></A></P></LI><LI CLASS="li-enumerate"><EM><FONT COLOR=black><FONT SIZE=3>In Scrabble a &#X201C;bingo&#X201D; is when you play all seven tiles in
*''Modify the previous program so that it prints the largest set
of anagrams first, followed by the second largest set, and so on.''
''
''
 
*''In Scrabble a &#X201C;bingo&#X201D; is when you play all seven tiles in
your rack, along with a letter on the board, to form an eight-letter
your rack, along with a letter on the board, to form an eight-letter
word. What set of 8 letters forms the most possible bingos?
word. What set of 8 letters forms the most possible bingos?
Hint: there are seven.</FONT></FONT></EM><P><A NAME="@default1151"></A></P></LI><LI CLASS="li-enumerate"><EM><EM><FONT COLOR=black><FONT SIZE=3>Two words form a &#X201C;metathesis pair&#X201D; if you can transform one
Hint: there are seven.''
into the other by swapping two letters</FONT></FONT></EM></EM><SUP><A NAME="text27" HREF="#note27"><EM><EM><FONT COLOR=black><FONT SIZE=3>3</FONT></FONT></EM></EM></A></SUP><EM><EM><FONT COLOR=black><FONT SIZE=3>; for example,
 
*''''Two words form a &#X201C;metathesis pair&#X201D; if you can transform one
into the other by swapping two letters''''<SUP>''''3''''</SUP>''''; for example,
&#X201C;converse&#X201D; and &#X201C;conserve.&#X201D; Write a program that finds all of
&#X201C;converse&#X201D; and &#X201C;conserve.&#X201D; Write a program that finds all of
the metathesis pairs in the dictionary. Hint: don&#X2019;t test all pairs
the metathesis pairs in the dictionary. Hint: don&#X2019;t test all pairs
of words, and don&#X2019;t test all possible swaps.</FONT></FONT></EM></EM><P><EM><EM><FONT COLOR=black><FONT SIZE=3>You can download a solution from </FONT></FONT></EM></EM><EM><EM><FONT COLOR=black><FONT SIZE=3><TT>thinkpython.com/code/anagram_sets.py</TT></FONT></FONT></EM></EM><EM><EM><FONT COLOR=black><FONT SIZE=3>.</FONT></FONT></EM></EM></P></LI></OL></DIV><DIV CLASS="theorem"><FONT COLOR=black><FONT SIZE=3><B>Exercise&#XA0;5</B></FONT></FONT><FONT COLOR=black><FONT SIZE=3>&#XA0;&#XA0;</FONT></FONT><P><A NAME="@default1152"></A><FONT COLOR=black><FONT SIZE=3><EM>
of words, and don&#X2019;t test all possible swaps.''''
</EM></FONT></FONT><A NAME="@default1153"></A></P><P><FONT COLOR=black><FONT SIZE=3><EM>Here&#X2019;s another Car Talk Puzzler</EM></FONT></FONT><SUP><A NAME="text28" HREF="#note28"><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>
''''You can download a solution from ''''''''<TT>thinkpython.com/code/anagram_sets.py</TT>''''''''.''''
 
</DIV><DIV CLASS="theorem">'''Exercise&#XA0;5'''&#XA0;&#XA0;
''
''
 
''Here&#X2019;s another Car Talk Puzzler''<SUP>''4''</SUP>'':''
<BLOCKQUOTE CLASS="quote">''
What is the longest English word, that remains a valid English word,
What is the longest English word, that remains a valid English word,
as you remove its letters one at a time?</EM></FONT></FONT><P><FONT COLOR=black><FONT SIZE=3><EM>Now, letters can be removed from either end, or the middle, but you
as you remove its letters one at a time?''
''Now, letters can be removed from either end, or the middle, but you
can&#X2019;t rearrange any of the letters. Every time you drop a letter, you
can&#X2019;t rearrange any of the letters. Every time you drop a letter, you
wind up with another English word. If you do that, you&#X2019;re eventually
wind up with another English word. If you do that, you&#X2019;re eventually
Line 401: Line 664:
English word&#X2014;one that&#X2019;s found in the dictionary. I want to know
English word&#X2014;one that&#X2019;s found in the dictionary. I want to know
what&#X2019;s the longest word and how many letters does it
what&#X2019;s the longest word and how many letters does it
have?</EM></FONT></FONT></P><P><FONT COLOR=black><FONT SIZE=3><EM>I&#X2019;m going to give you a little modest example: Sprite. Ok? You start
have?''
 
''I&#X2019;m going to give you a little modest example: Sprite. Ok? You start
off with sprite, you take a letter off, one from the interior of the
off with sprite, you take a letter off, one from the interior of the
word, take the r away, and we&#X2019;re left with the word spite, then we
word, take the r away, and we&#X2019;re left with the word spite, then we
take the e off the end, we&#X2019;re left with spit, we take the s off, we&#X2019;re
take the e off the end, we&#X2019;re left with spit, we take the s off, we&#X2019;re
left with pit, it, and I.
left with pit, it, and I.
</EM></FONT></FONT></P></BLOCKQUOTE><P><A NAME="@default1154"></A><FONT COLOR=black><FONT SIZE=3><EM>
''
</EM></FONT></FONT><A NAME="@default1155"></A></P><P><FONT COLOR=black><FONT SIZE=3><EM>Write a program to find all words that can be reduced in this way,
</BLOCKQUOTE>
and then find the longest one.</EM></FONT></FONT></P><P><FONT COLOR=black><FONT SIZE=3><EM>This exercise is a little more challenging than most, so here are
''
some suggestions:</EM></FONT></FONT></P><OL CLASS="enumerate" type=1><LI CLASS="li-enumerate"><FONT COLOR=black><FONT SIZE=3><EM>You might want to write a function that takes a word and
''
 
''Write a program to find all words that can be reduced in this way,
and then find the longest one.''
 
''This exercise is a little more challenging than most, so here are
some suggestions:''
 
*''You might want to write a function that takes a word and
computes a list of all the words that can be formed by removing one
computes a list of all the words that can be formed by removing one
letter. These are the &#X201C;children&#X201D; of the word.</EM></FONT></FONT><P><A NAME="@default1156"></A><FONT COLOR=black><FONT SIZE=3><EM>
letter. These are the &#X201C;children&#X201D; of the word.''
</EM></FONT></FONT><A NAME="@default1157"></A></P></LI><LI CLASS="li-enumerate"><FONT COLOR=black><FONT SIZE=3><EM>Recursively, a word is reducible if any of its children
''
''
 
*''Recursively, a word is reducible if any of its children
are reducible. As a base case, you can consider the empty
are reducible. As a base case, you can consider the empty
string reducible.</EM></FONT></FONT></LI><LI CLASS="li-enumerate"><FONT COLOR=black><FONT SIZE=3><EM>The wordlist I provided, </EM></FONT></FONT><FONT COLOR=black><FONT SIZE=3><EM><TT>words.txt</TT></EM></FONT></FONT><FONT COLOR=black><FONT SIZE=3><EM>, doesn&#X2019;t
string reducible.''
 
*''The wordlist I provided, ''''<TT>words.txt</TT>'''', doesn&#X2019;t
contain single letter words. So you might want to add
contain single letter words. So you might want to add
&#X201C;I&#X201D;, &#X201C;a&#X201D;, and the empty string.</EM></FONT></FONT></LI><LI CLASS="li-enumerate"><FONT COLOR=black><FONT SIZE=3><EM>To improve the performance of your program, you might want
&#X201C;I&#X201D;, &#X201C;a&#X201D;, and the empty string.''
to memoize the words that are known to be reducible.</EM></FONT></FONT></LI></OL><P><FONT COLOR=black><FONT SIZE=3><EM>You can see my solution at </EM></FONT></FONT><FONT COLOR=black><FONT SIZE=3><EM><TT>thinkpython.com/code/reducible.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="note25" HREF="#text25"><FONT COLOR=black><FONT SIZE=3>1</FONT></FONT></A></DT><DD CLASS="dd-thefootnotes"><FONT COLOR=black><FONT SIZE=3>In Python 3.0, <TT>zip</TT> returns an
*''To improve the performance of your program, you might want
to memoize the words that are known to be reducible.''
 
''You can see my solution at ''''<TT>thinkpython.com/code/reducible.py</TT>''''.''
</DIV><HR CLASS="footnoterule"><DL CLASS="thefootnotes"><DT CLASS="dt-thefootnotes">
1</DT><DD CLASS="dd-thefootnotes">In Python 3.0, <TT>zip</TT> returns an
iterator of tuples, but for most purposes, an iterator behaves like
iterator of tuples, but for most purposes, an iterator behaves like
a list.
a list.
</FONT></FONT></DD><DT CLASS="dt-thefootnotes"><A NAME="note26" HREF="#text26"><FONT COLOR=black><FONT SIZE=3>2</FONT></FONT></A></DT><DD CLASS="dd-thefootnotes"><FONT COLOR=black><FONT SIZE=3>This behavior is
</DD><DT CLASS="dt-thefootnotes">2</DT><DD CLASS="dd-thefootnotes">This behavior is
slightly different in Python 3.0.
slightly different in Python 3.0.
</FONT></FONT></DD><DT CLASS="dt-thefootnotes"><A NAME="note27" HREF="#text27"><FONT COLOR=black><FONT SIZE=3>3</FONT></FONT></A></DT><DD CLASS="dd-thefootnotes"><FONT COLOR=black><FONT SIZE=3>This exercise is
</DD><DT CLASS="dt-thefootnotes">3</DT><DD CLASS="dd-thefootnotes">This exercise is
inspired by an example at <TT>puzzlers.org</TT>.
inspired by an example at <TT>puzzlers.org</TT>.
</FONT></FONT></DD><DT CLASS="dt-thefootnotes"><A NAME="note28" HREF="#text28"><FONT COLOR=black><FONT SIZE=3>4</FONT></FONT></A></DT><DD CLASS="dd-thefootnotes"><FONT COLOR=black><FONT SIZE=3>
</DD><DT CLASS="dt-thefootnotes">4</DT><DD CLASS="dd-thefootnotes">
<TT>www.cartalk.com/content/puzzler/transcripts/200651</TT>
<TT>www.cartalk.com/content/puzzler/transcripts/200651</TT>
</FONT></FONT></DD></DL>
</DD></DL>
<HR>
<HR>
<A HREF="book012.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="book014.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 12  Tuples

12.1  Tuples are immutable

A tuple is a sequence of values. The values can be any type, and they are indexed by integers, so in that respect tuples are a lot like lists. The important difference is that tuples are immutable.



Syntactically, a tuple is a comma-separated list of values:

>>> t = 'a', 'b', 'c', 'd', 'e'

Although it is not necessary, it is common to enclose tuples in parentheses:

>>> t = ('a', 'b', 'c', 'd', 'e')

To create a tuple with a single element, you have to include the final comma:


>>> t1 = ('a',)
>>> type(t1)
<type 'tuple'>

Without the comma, Python treats ('a') as a string in parentheses:

>>> t2 = ('a')
>>> type(t2)
<type 'str'>

Another way to create a tuple is the built-in function tuple. With no argument, it creates an empty tuple:


>>> t = tuple()
>>> print t
()

If the argument is a sequence (string, list or tuple), the result is a tuple with the elements of the sequence:

>>> t = tuple('lupins')
>>> print t
('l', 'u', 'p', 'i', 'n', 's')

Because tuple is the name of a built-in function, you should avoid using it as a variable name.

Most list operators also work on tuples. The bracket operator indexes an element:


>>> t = ('a', 'b', 'c', 'd', 'e')
>>> print t[0]
'a'

And the slice operator selects a range of elements.



>>> print t[1:3]
('b', 'c')

But if you try to modify one of the elements of the tuple, you get an error:



>>> t[0] = 'A'
TypeError: object doesn't support item assignment

You can’t modify the elements of a tuple, but you can replace one tuple with another:

>>> t = ('A',) + t[1:]
>>> print t
('A', 'b', 'c', 'd', 'e')

=== 12.2  Tuple assignment ===





It is often useful to swap the values of two variables. With conventional assignments, you have to use a temporary variable. For example, to swap a and b:

>>> temp = a
>>> a = b
>>> b = temp

This solution is cumbersome; tuple assignment is more elegant:

>>> a, b = b, a

The left side is a tuple of variables; the right side is a tuple of expressions. Each value is assigned to its respective variable. All the expressions on the right side are evaluated before any of the assignments.

The number of variables on the left and the number of values on the right have to be the same:


>>> a, b = 1, 2, 3
ValueError: too many values to unpack

More generally, the right side can be any kind of sequence (string, list or tuple). For example, to split an email address into a user name and a domain, you could write:



>>> addr = 'monty@python.org'
>>> uname, domain = addr.split('@')

The return value from split is a list with two elements; the first element is assigned to uname, the second to domain.

>>> print uname
monty
>>> print domain
python.org

=== 12.3  Tuples as return values ===




Strictly speaking, a function can only return one value, but if the value is a tuple, the effect is the same as returning multiple values. For example, if you want to divide two integers and compute the quotient and remainder, it is inefficient to compute x/y and then x%y. It is better to compute them both at the same time.

The built-in function divmod takes two arguments and returns a tuple of two values, the quotient and remainder. You can store the result as a tuple:

>>> t = divmod(7, 3)
>>> print t
(2, 1)

Or use tuple assignment to store the elements separately:


>>> quot, rem = divmod(7, 3)
>>> print quot
2
>>> print rem
1

Here is an example of a function that returns a tuple:

def min_max(t):
    return min(t), max(t)

max and min are built-in functions that find the largest and smallest elements of a sequence. min_max computes both and returns a tuple of two values.



12.4  Variable-length argument tuples

Functions can take a variable number of arguments. A parameter name that begins with * gathers arguments into a tuple. For example, printall takes any number of arguments and prints them:

def printall(*args):
    print args

The gather parameter can have any name you like, but args is conventional. Here’s how the function works:

>>> printall(1, 2.0, '3')
(1, 2.0, '3')

You can combine the gather operator with required and positional arguments:

def pointless(required, optional=0, *args):
    print required, optional, args

Run this function with 1, 2, 3 and 4 or more arguments and make sure you understand what it does.



The complement of gather is scatter. If you have a sequence of values and you want to pass it to a function as multiple arguments, you can use the * operator. For example, divmod takes exactly two arguments; it doesn’t work with a tuple:


>>> t = (7, 3)
>>> divmod(t)
TypeError: divmod expected 2 arguments, got 1

But if you scatter the tuple, it works:

>>> divmod(*t)
(2, 1)
Exercise 1  

Many of the built-in functions use variable-length argument tuples. For example, 'max' and 'min' can take any number of arguments: ' '

''>>> max(1,2,3)
3
''

But 'sum' does not.

''>>> sum(1,2,3)
TypeError: sum expected at most 2 arguments, got 3
''

Write a function called 'sumall' that takes any number of arguments and returns their sum.

=== 12.5  Lists and tuples ===



zip is a built-in function that takes two or more sequences and “zips” them into a list1 of tuples where each tuple contains one element from each sequence.

This example zips a string and a list:

>>> s = 'abc'
>>> t = [0, 1, 2]
>>> zip(s, t)
[('a', 0), ('b', 1), ('c', 2)]

The result is a list of tuples where each tuple contains a character from the string and the corresponding element from the list.

If the sequences are not the same length, the result has the length of the shorter one.

>>> zip('Anne', 'Elk')
[('A', 'E'), ('n', 'l'), ('n', 'k')]

You can use tuple assignment in a for loop to traverse a list of tuples:



t = [('a', 0), ('b', 1), ('c', 2)]
for letter, number in t:
    print number, letter

Each time through the loop, Python selects the next tuple in the list and assigns the elements to letter and number. The output of this loop is:

0 a
1 b
2 c

If you combine zip, for and tuple assignment, you get a useful idiom for traversing two (or more) sequences at the same time. For example, has_match takes two sequences, t1 and t2, and returns True if there is an index i such that t1[i] == t2[i]:

def has_match(t1, t2):
    for x, y in zip(t1, t2):
        if x == y:
            return True
    return False

If you need to traverse the elements of a sequence and their indices, you can use the built-in function enumerate:



for index, element in enumerate('abc'):
    print index, element

The output of this loop is:

0 a
1 b
2 c

Again.

12.6  Dictionaries and tuples

Dictionaries have a method called items that returns a list of tuples, where each tuple is a key-value pair2.

>>> d = {'a':0, 'b':1, 'c':2}
>>> t = d.items()
>>> print t
[('a', 0), ('c', 2), ('b', 1)]

As you should expect from a dictionary, the items are in no particular order.

Conversely, you can use a list of tuples to initialize a new dictionary:

>>> t = [('a', 0), ('c', 2), ('b', 1)]
>>> d = dict(t)
>>> print d
{'a': 0, 'c': 2, 'b': 1}

Combining dict with zip yields a concise way to create a dictionary:

>>> d = dict(zip('abc', range(3)))
>>> print d
{'a': 0, 'c': 2, 'b': 1}

The dictionary method update also takes a list of tuples and adds them, as key-value pairs, to an existing dictionary.




Combining items, tuple assignment and for, you get the idiom for traversing the keys and values of a dictionary:

for key, val in d.items():
    print val, key

The output of this loop is:

0 a
2 c
1 b

Again.



It is common to use tuples as keys in dictionaries (primarily because you can’t use lists). For example, a telephone directory might map from last-name, first-name pairs to telephone numbers. Assuming that we have defined last, first and number, we could write:

directory[last,first] = number

The expression in brackets is a tuple. We could use tuple assignment to traverse this dictionary.

for last, first in directory:
    print first, last, directory[last,first]

This loop traverses the keys in directory, which are tuples. It assigns the elements of each tuple to last and first, then prints the name and corresponding telephone number.

There are two ways to represent tuples in a state diagram. The more detailed version shows the indices and elements just as they appear in a list. For example, the tuple ('Cleese', 'John') would appear:


<IMG SRC="book020.png">

But in a larger diagram you might want to leave out the details. For example, a diagram of the telephone directory might appear:

<IMG SRC="book021.png">

Here the tuples are shown using Python syntax as a graphical shorthand.

The telephone number in the diagram is the complaints line for the BBC, so please don’t call it.

12.7  Comparing tuples

The comparison operators work with tuples and other sequences; Python starts by comparing the first element from each sequence. If they are equal, it goes on to the next elements, and so on, until it finds elements that differ. Subsequent elements are not considered (even if they are really big).

>>> (0, 1, 2) < (0, 3, 4)
True
>>> (0, 1, 2000000) < (0, 3, 4)
True

The sort function works the same way. It sorts primarily by first element, but in the case of a tie, it sorts by second element, and so on.

This feature lends itself to a pattern called DSU for

Decorate
a sequence by building a list of tuples with one or more sort keys preceding the elements from the sequence,
Sort
the list of tuples, and
Undecorate
by extracting the sorted elements of the sequence.




For example, suppose you have a list of words and you want to sort them from longest to shortest:

def sort_by_length(words):
    t = []
    for word in words:
       t.append((len(word), word))

    t.sort(reverse=True)

    res = []
    for length, word in t:
        res.append(word)
    return res

The first loop builds a list of tuples, where each tuple is a word preceded by its length.

sort compares the first element, length, first, and only considers the second element to break ties. The keyword argument reverse=True tells sort to go in decreasing order.



The second loop traverses the list of tuples and builds a list of words in descending order of length.

Exercise 2  

In this example, ties are broken by comparing words, so words with the same length appear in alphabetical order. For other applications you might want to break ties at random. Modify this example so that words with the same length appear in random order. Hint: see the 'random' function in the 'random' module. ' '

=== 12.8  Sequences of sequences ===



I have focused on lists of tuples, but almost all of the examples in this chapter also work with lists of lists, tuples of tuples, and tuples of lists. To avoid enumerating the possible combinations, it is sometimes easier to talk about sequences of sequences.

In many contexts, the different kinds of sequences (strings, lists and tuples) can be used interchangeably. So how and why do you choose one over the others?




To start with the obvious, strings are more limited than other sequences because the elements have to be characters. They are also immutable. If you need the ability to change the characters in a string (as opposed to creating a new string), you might want to use a list of characters instead.

Lists are more common than tuples, mostly because they are mutable. But there are a few cases where you might prefer tuples:

  • In some contexts, like a return statement, it is

syntactically simpler to create a tuple than a list. In other contexts, you might prefer a list.

  • If you want to use a sequence as a dictionary key, you

have to use an immutable type like a tuple or string.

  • If you are passing a sequence as an argument to a function,

using tuples reduces the potential for unexpected behavior due to aliasing.

Because tuples are immutable, they don’t provide methods like sort and reverse, which modify existing lists. But Python provides the built-in functions sorted and reversed, which take any sequence as a parameter and return a new list with the same elements in a different order.



12.9  Debugging

Lists, dictionaries and tuples are known generically as data structures; in this chapter we are starting to see compound data structures, like lists of tuples, and dictionaries that contain tuples as keys and lists as values. Compound data structures are useful, but they are prone to what I call shape errors; that is, errors caused when a data structure has the wrong type, size or composition. For example, if you are expecting a list with one integer and I give you a plain old integer (not in a list), it won’t work.



To help debug these kinds of errors, I have written a module called structshape that provides a function, also called structshape, that takes any kind of data structure as an argument and returns a string that summarizes its shape. You can download it from thinkpython.com/code/structshape.py

Here’s the result for a simple list:

>>> from structshape import structshape
>>> t = [1,2,3]
>>> print structshape(t)
list of 3 int

A fancier program might write “list of 3 ints,” but it was easier not to deal with plurals. Here’s a list of lists:

>>> t2 = [[1,2], [3,4], [5,6]]
>>> print structshape(t2)
list of 3 list of 2 int

If the elements of the list are not the same type, structshape groups them, in order, by type:

>>> t3 = [1, 2, 3, 4.0, '5', '6', [7], [8], 9]
>>> print structshape(t3)
list of (3 int, float, 2 str, 2 list of int, int)

Here’s a list of tuples:

>>> s = 'abc'
>>> lt = zip(t, s)
>>> print structshape(lt)
list of 3 tuple of (int, str)

And here’s a dictionary with 3 items that map integers to strings.

>>> d = dict(lt) 
>>> print structshape(d)
dict of 3 int->str

If you are having trouble keeping track of your data structures, structshape can help.

12.10  Glossary

tuple:
An immutable sequence of elements.
tuple assignment:
An assignment with a sequence on the right side and a tuple of variables on the left. The right side is evaluated and then its elements are assigned to the variables on the left.
gather:
The operation of assembling a variable-length argument tuple.
scatter:
The operation of treating a sequence as a list of arguments.
DSU:
Abbreviation of “decorate-sort-undecorate,” a pattern that involves building a list of tuples, sorting, and extracting part of the result.
data structure:
A collection of related values, often organized in lists, dictionaries, tuples, etc.
shape (of a data structure):
A summary of the type, size and composition of a data structure.

=== 12.11  Exercises ===

Exercise 3  

Write a function called most_frequent that takes a string and prints the letters in decreasing order of frequency. Find text samples from several different languages and see how letter frequency varies between languages. Compare your results with the tables at 'wikipedia.org/wiki/Letter_frequencies'.

Exercise 4  

More anagrams!

  • Write a program

that reads a word list from a file (see Section '9.1') and prints all the sets of words that are anagrams. Here is an example of what the output might look like:

''['deltas', 'desalt', 'lasted', 'salted', 'slated', 'staled']
['retainers', 'ternaries']
['generating', 'greatening']
['resmelts', 'smelters', 'termless']
''

Hint: you might want to build a dictionary that maps from a set of letters to a list of words that can be spelled with those letters. The question is, how can you represent the set of letters in a way that can be used as a key?

  • Modify the previous program so that it prints the largest set

of anagrams first, followed by the second largest set, and so on.

  • In Scrabble a “bingo” is when you play all seven tiles in

your rack, along with a letter on the board, to form an eight-letter word. What set of 8 letters forms the most possible bingos? Hint: there are seven.

  • 'Two words form a “metathesis pair” if you can transform one

into the other by swapping two letters''3''; for example, “converse” and “conserve.” Write a program that finds all of the metathesis pairs in the dictionary. Hint: don’t test all pairs of words, and don’t test all possible swaps.' 'You can download a solution from '''thinkpython.com/code/anagram_sets.py'''.'

Exercise 5  

Here’s another Car Talk Puzzler4:

What is the longest English word, that remains a valid English word, as you remove its letters one at a time? Now, letters can be removed from either end, or the middle, but you can’t rearrange any of the letters. Every time you drop a letter, you wind up with another English word. If you do that, you’re eventually going to wind up with one letter and that too is going to be an English word—one that’s found in the dictionary. I want to know what’s the longest word and how many letters does it have?

I’m going to give you a little modest example: Sprite. Ok? You start off with sprite, you take a letter off, one from the interior of the word, take the r away, and we’re left with the word spite, then we take the e off the end, we’re left with spit, we take the s off, we’re left with pit, it, and I.

Write a program to find all words that can be reduced in this way, and then find the longest one.

This exercise is a little more challenging than most, so here are some suggestions:

  • You might want to write a function that takes a word and

computes a list of all the words that can be formed by removing one letter. These are the “children” of the word.

  • Recursively, a word is reducible if any of its children

are reducible. As a base case, you can consider the empty string reducible.

  • The wordlist I provided, 'words.txt', doesn’t

contain single letter words. So you might want to add “I”, “a”, and the empty string.

  • To improve the performance of your program, you might want

to memoize the words that are known to be reducible.

You can see my solution at 'thinkpython.com/code/reducible.py'.


1
In Python 3.0, zip returns an iterator of tuples, but for most purposes, an iterator behaves like a list.
2
This behavior is slightly different in Python 3.0.
3
This exercise is inspired by an example at puzzlers.org.
4
www.cartalk.com/content/puzzler/transcripts/200651

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