\chapter{Lists part 2}
\label{lec-lists2}
\section{Lists and for loops}
The \myidx{\pythoninline{for}} loop also works with lists. The generalized
syntax of a \pythoninline{for} loop is:
\begin{python}
for VARIABLE in LIST:
   BODY
\end{python}
This statement is equivalent to:
\begin{python}
i = 0
while i < len(LIST):
   VARIABLE = LIST[i]
   BODY
   i += 1
\end{python}
The \pythoninline{for} loop is more concise because we can eliminate the loop
variable, \pythoninline{i}. Here is the \pythoninline{horsemen~while} loop written with a
\pythoninline{for} loop. 
\begin{python}
for horseman in horsemen:
   print horseman
\end{python}
It almost reads like English: For (every) \pythoninline{horseman} in
(the list of) \pythoninline{horsemen}, print (the name of the)
\pythoninline{horseman}. 

Any list expression can be used in a for loop:
\begin{python}
for number in range(20):
   if number % 3 == 0:
       print  number

for fruit in ["banana", "apple", "quince"]:
   print "I like to eat " + fruit + "s!"
\end{python}
The first example prints all the multiples of 3 between 0 and 19. The
second example expresses enthusiasm for various fruits.

Since lists are mutable, it is often desirable to traverse a list,
modifying each of its elements. The following squares all the numbers
from 1 to 5:
\begin{python}
numbers = [1, 2, 3, 4, 5]

for index in range(len(numbers)):
   numbers[index] = numbers[index]**2
\end{python}
Take a moment to think about \pythoninline{range(len(numbers))} until
you understand 
how it works. We are interested here in both the \emph{value} and its
\emph{index} within the list, so that we can assign a new value to
it.

This pattern is common enough that Python provides a nicer way to
implement it:
\begin{python}
numbers = [1, 2, 3, 4, 5]

for index, value in enumerate(numbers):
   numbers[index] = value**2
\end{python}
\pythoninline{enumerate} generates both the \pythoninline{index} and
the \pythoninline{value} associated with it during the list traversal.
Try this next example to see more clearly how enumerate works: 
\begin{pythonInteractive}
>>> for index, value in enumerate(['banana', 'apple', 'pear', 'quince']):
...    print index, value 
...
0 banana
1 apple
2 pear
3 quince
>>>
\end{pythonInteractive}

\section{List parameters}
Passing a list as an argument actually passes a reference to the
list, not a copy of the list. Since lists are mutable changes made to
the parameter change the argument as well. For example, the function
below takes a list as an argument and multiplies each element in the
list by 2:
\begin{python}
def double_stuff(a_list):
   for index, value in enumerate(a_list):
       a_list[index] = 2 * value
\end{python}
If we put \pythoninline{double\_stuff} in a file named
\pythoninline{double\_stuff.py}, we can test it out like this: 
\begin{pythonInteractive}
>>> from double_stuff import double_stuff
>>> things = [2, 5, 'Spam', 9.5]
>>> double_stuff(things)
>>> things
[4, 10, 'SpamSpam', 19.0]
>>>
\end{pythonInteractive}
The parameter \pythoninline{a\_list} and the variable things are
aliases for the same object. The state diagram looks like this:

\begin{center}
\includegraphics[scale=1]{figures/list-params-fig}
\end{center}

Since the list object is shared by two frames, we drew it between
them. If a function modifies a list parameter, the caller sees the
change.
 
\section{Pure functions and modifiers}
\label{sec-pure-funcs}
Functions which take lists as arguments and change them during
execution are called \myidx{modifiers} and the changes they make are
called \myidx{side effects}.
A \myidx{pure function} does not produce side effects. It
communicates with the calling program only through parameters, which
it does not modify, and a return value. Here is
\pythoninline{double\_stuff} written as a pure function:
\begin{python}
def double_stuff(a_list):
   new_list = []
   for value in a_list:
       new_list += [2 * value]
   return new_list
\end{python}
This version of \pythoninline{double\_stuff} does not change its arguments:
\begin{pythonInteractive}
>>> from double_stuff import double_stuff
>>> things = [2, 5, 'Spam', 9.5]
>>> double_stuff(things)
[4, 10, 'SpamSpam', 19.0]
>>> things
[2, 5, 'Spam', 9.5]
>>>
\end{pythonInteractive}
To use the pure function version of \pythoninline{double\_stuff} to
modify \pythoninline{things}, you would assign the return value back
to \pythoninline{things}:
\begin{pythonInteractive}
>>> things = double_stuff(things)
>>> things
[4, 10, 'SpamSpam', 19.0]
>>>
\end{pythonInteractive}

\section{Which is better?}
Anything that can be done with modifiers can also be done with pure
functions. In fact, some programming languages only allow pure
functions. There is some evidence that programs that use pure
functions are faster to develop and less error-prone than programs
that use modifiers. Nevertheless, modifiers are convenient at times,
and in some cases, functional programs are less efficient.
In general, we recommend that you write pure functions whenever it is
reasonable to do so and resort to modifiers only if there is a
compelling advantage. This approach might be called a
\myidx{functional programming style}.

\section{Nested lists}
A nested list is a list that appears as an element in another
list. In this list, the element with index 3 is a nested list:
\begin{pythonInteractive}
>>> nested = ["hello", 2.0, 5, [10, 20]]
\end{pythonInteractive}
If we print \pythoninline{nested[3]}, we get \pythoninline{[10, 20]}.
To extract an element from the nested list, we can proceed in two steps:
\begin{pythonInteractive}
>>> elem = nested[3]
>>> elem[0]
10
\end{pythonInteractive}
Or we can combine them:
\begin{pythonInteractive}
>>> nested[3][1]
20
\end{pythonInteractive}
Bracket operators evaluate from left to right, so this expression
gets the third element of nested and extracts the first element
from it.

\section{Matrices}
\label{sec-matrices-nested}
Nested lists are often used to represent matrices. For example, the
matrix:
\begin{center}
\includegraphics[scale=1]{figures/matrix-fig}
\end{center}
might be represented as:
\begin{pythonInteractive}
>>> matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
\end{pythonInteractive}
\pythoninline{matrix} is a list with three elements, where each
element is a row of the matrix. We can select an entire row from the
matrix in the usual way: 
\begin{pythonInteractive}
>>> matrix[1]
[4, 5, 6]
\end{pythonInteractive}

Or we can extract a single element from the matrix using the
double-index form:
\begin{pythonInteractive}
>>> matrix[1][1]
5
\end{pythonInteractive}
The first index selects the row, and the second index selects the
column. Although this way of representing matrices is common, it is
not the only possibility. A small variation is to use a list of
columns instead of a list of rows. Later we will see a more radical
alternative using a dictionary.

\section{Strings and lists}
Python has a command called \pythoninline{list} that takes a sequence
type as an argument and creates a list out of its elements.
\begin{pythonInteractive}
>>> list("Crunchy Frog")
['C', 'r', 'u', 'n', 'c', 'h', 'y', ' ', 'F', 'r', 'o', 'g']
\end{pythonInteractive}
There is also a \pythoninline{str} command that takes any Python value as an
argument and returns a string representation of it.
\begin{pythonInteractive}
>>> str(5)
'5'
>>> str(None)
'None'
>>> str(list("nope"))
"['n', 'o', 'p', 'e']"
\end{pythonInteractive}
As we can see from the last example, \pythoninline{str} can't be used
to join a list of characters together. To do this we could use the
string method \pythoninline{join}:
\begin{pythonInteractive}
>>> char_list = list("Frog")
>>> char_list
['F', 'r', 'o', 'g']
>>> ''.join(char_list)
'Frog'
\end{pythonInteractive}

To go in the opposite direction, the \pythoninline{split} method
breaks a string into a list of words. By default, any number of
whitespace characters is considered a word boundary:

\begin{pythonInteractive}
>>> song = "The rain in Spain..."
>>> song.split()
['The', 'rain', 'in', 'Spain...']
\end{pythonInteractive}
An optional argument called a \myidx{delimiter} can be used to
specify which characters to use as word boundaries. The following
example uses the string \pythoninline{ai} as the delimiter (which
doesn't appear in the result):
\begin{pythonInteractive}
>>> song.split('ai')
['The r', 'n in Sp', 'n...']
\end{pythonInteractive}

\section{Glossary}
\begin{description}
\item[modifier:]A function which changes its arguments inside the
  function body. Only mutable types can be changed by modifiers.
\item[side effect:]A change in the state of a program made by calling
  a function that is not a result of reading the return value from
  the function. Side effects can only be produced by modifiers.
\item[pure function:]A function which has no side effects. Pure
  functions only make changes to the calling program through their
  return values.
\item[delimiter:]A character or string used to indicate where a
  string should be split.
\end{description}

\newpage
\section{Laboratory exercises}
\begin{enumerate}
\item
\begin{python}
song = "The rain in Spain..."
\end{python}
Describe the relationship between
\pythoninline{' '.join(song.split())} 
and \pythoninline{song}. Are they the same for all strings? When would they be
different?
\begin{answerspace}




zend
\end{answerspace}

\item Write a function \pythoninline{replace(s,~old,~new)} that replaces all
occurrences of \pythoninline{old} with \pythoninline{new} in a string
\pythoninline{s}. 
\begin{python}
def myreplace(s, old, new):
   """
     >>> myreplace('Mississippi', 'i', 'I')
     'MIssIssIppI'
     >>> s = 'I love spom!  Spom is my favorite food.  Spom, spom, spom, yum!'
     >>> myreplace(s, 'om', 'am')
     'I love spam!  Spam is my favorite food.  Spam, spam, spam, yum!'
     >>> myreplace(s, 'o', 'a')
     'I lave spam!  Spam is my favarite faad.  Spam, spam, spam, yum!'
   """
\end{python}
Your solution should pass the doctests above, but don't use the
existing string replace method.

\item \label{matrix-mult} Complete the body of the \pythoninline{matrix\_multiply}
  function below so that it passes the doctests.  You will need three
  nested loops.
\begin{python}
def matrix_multiply(amatrix, bmatrix):
    """ Return a matrix which is the result of multiplying amatrix and bmatrix.
    Assume that amatrix is an NxM matrix and bmatrix is an MxP matrix (this means
    amatrix has N rows and M columns, while bmatrix has M rows and P columns).
    The resulting matrix will be an NxP matrix.
    A matrix is represented as a list of lists as shown below.

                [1 4]
    The matrix  [2 5]  is represented by this list  [[1,4],[2,5],[3,6]]
                [3 6] 
    
    >>> matrix_multiply([[1,2]],[[3],[4]])
    [[11]]
    >>> matrix_multiply([[1],[2]], [[3,4]])
    [[3, 6], [4, 8]]
    >>> matrix_multiply([[1,2,3],[4,5,6]], [[1,4],[2,5],[3,6]])
    [[14, 32], [32, 77]]
    >>> matrix_multiply([[1,2,3],[4,5,6]], [[1,4,7,10],[2,5,8,11],[3,6,9,12]])
    [[14, 32], [32, 77], [50, 122], [68, 167]]
    """
\end{python}
\end{enumerate}
