Tutorial, Part 4: Lists, for loops, and numpy arrays

Contact: compwiki@physics.utoronto.ca

To finish our tutorial, we are going to introduce lists and for loops , which are loops that iterate over elements of lists. We are also going to provide you with tips on how to further explore Python using its built-in help facilities.

1. Review

In the last section we introduced if statements and while loops. Both of these concepts are useful tools in writing programs. While loops can be used to evaluate and edit data up until it reaches a desired point. If statements can also be used in a variety of different situations. Amidst theses two larger topics we learned about Boolean variables and logical operators, which are essential to make while loops and if statements work. Let's try to use all that we have learned, including things from previous sections, to make a program.

Activity 0: Do the following:
  • Let's start by making a function that takes two user inputs and adds them together.
  • def add_string():
        #raw_input allows you to enter anything you want
        #therefore you can use raw_input to enter a string
        string1 = raw_input('Enter a word. ')
        string2 = raw_input('Enter another word. ')
        final_string = string1 + string2    
        return final_string
  • This is quite a simple program but it is meant to show you the use of the raw_input() function. It also shows that you can add two strings together with the + operator. Note that not all other operators will work.
  • Now let's make another function.
  • def match_condition():
        s = add_string()
        z = False # setup some initial conditions
        #len() lets you find the length of the object within the
        #brackets. It will not work for all types of objects.
        length = len(s)
        while length > 0:
            if s.startswith('z'): # check to see whether the first letter in the string is a z
                length = 0 # set length equal to 0 so the while loop will stop
                z = True
                s = s.replace(s[0],'',1) # take the first letter in the string and replace it with nothing
                length -= 1 # subtract one from the length so the while loop will eventually end
        if z == True:
            print 'Your string matched the condition.'
            print 'Your string did not match the condition. Try again.'        
            match_condition() # rerun the program so that you can guess again
  • So what exactly is this program doing? It takes the two words that you enter and checks to see whether or not a 'z' is within them. It looks like a useless function but you can modify it or use it as a template to search other data for certain characteristics.
  • Some important notes to make are that the raw_input() function will default whatever you enter to a string so there is no need for you to use '' when entering data. You may be wondering what the functions s.startswith() and s.replace() are for. They are functions specific to the string class and what they do should be obvious by their name. Another confusing element within this function is the use of s[0]. The square brackets indicate an index or a location within s, where 0 is the first element. For example if str = 'abc123' then str[0] is 'a' and str[3] is '1' and so forth. You will learn more about this indexing in this part of the tutorial when you do lists.
  • Some of you may be wondering how match_condition() is called within itself. This is called recursion, which is a very useful tool. In this example calling match_condition() assumes you want to guess again. It will continue to call itself until z==True, which is when the program terminates without the function being called again.

2. A first introduction to lists and why they are useful

So far we have dealt with data values and data variables "one at a time", so to speak, so that each variable can only have one value at a time; for example the assignment statement x = 2 assigns the integer 2 to the variable x , and x = x + 1 updates the variable x to have the value 3. But suppose we want to define a variable like a force vector or a collection of birthdays that we know consists of multiple components? In that case, it makes life easier to group several numbers (or strings, or even other variables) together into a single set with multiple components.

The Python set we'll use most often is the list, which is an ordered set in which Python keeps track of the position of each element in the set. A list is a comma-separated set of numbers (or strings, or other variables, or even other lists) enclosed by square brackets. Here is an assignment statement that creates a list assigned to the variable name my_list:
>>> my_list = [1, 2, 3, 4, 5]
>>> print my_list[1, 2, 3, 4, 5]
The variable my_list consists of five values. The first value is the integer 1, the second the integer 2, and so on. In Python, the first value of my_list is referenced using a special notation in which the index 0 corresponds to the first element, the index 1 corresponds to the second element, and so on, similar to the string example above. So my_list[0] corresponds to the value 1 and my_list[3] corresponds to the value 4. (For reasons we won't go into, several computer languages use this kind of zero-based indexing.) To see this indexing at work, look at the following example:
>>> print my_list[0]
>>> my_list[0] = 10
>>> print my_list
[10, 2, 3, 4, 5]
Here we used the indexing to refer to a particular value, and then changed that value using an assignment statement. (This will not work for strings.)

The following exercise will get you familiar with some of the basic properties of lists. Try the examples and create some of your own to better understand them. Our purpose here, in the spirit of the rest of the tutorial, is not to teach you everything there is to know about lists, but to focus on what you need to know to solve problems in physics. See the discussion of lists in the Python reference for more information.
Activity 1: Do the following:
  • Open up a Python shell and create a new list at the prompt
    >>> my_list = [5, 4, 3, 2, 1, 0]

    and print it by typing my_list at the next prompt.
  • Print the first and third values of my_list with my_list[0] and my_list[2].
  • The last element of my_list can be referenced by typing my_list[-1], the second last element by typing my_list[-2], and so on. At the prompt, print the last, second last, and third last elements of my_list.
  • The second, third and fourth elements can be accessed as a list by typing my_list[1:4] . Print my_list[1:4] at the prompt now. You will see that a list is printed, so my_list[1:4] is itself a list. The : (colon) notation instructs the interpreter to create a list starting with index 1 (the second element) and ending with integer up to, but not including, 4. This integer is 3, which corresponds to the fourth element. (We know it's confusing, but there are good reasons for this approach.)
  • The length of my_list can be found by typing len(my_list) . Do this now at the prompt.
  • Create a new list
    >>> my_new_list = ['apples', 'bananas', 'oranges']

    print it, and access the second element by typing my_new_list[1].
  • Here is practice with changing the values that appear within lists. Type the following:
    >>> my_new_list[1] = 'grapes'
    >>> my_new_list
    >>> my_list[0] = -9>>> my_list
  • You can concatenate lists --- stick them together --- using the + sign, and repeat them using the * sign. To see this, type the following and look at the results:
    >>> my_list + my_list
    >>> my_list * 2 
    >>> my_list * 5>>> my_list + my_new_list

    The last example created a list of numbers and strings.

To finish this section, we will briefly describe the range() function, which creates a list of numbers separated by equal increments. For example, this example creates a list called my_range_list:
>>> my_range_list = range(5)
>>> print my_range_list
[0, 1, 2, 3, 4]
Activity 2: Do the following:
  • Create a couple of lists using "range":
    >>> a = range(10)
    >>> print a
    >>> b = range(10, 2, -2)>>> print b
We will not say much more about range() here. Instead, we will now show you how to find out more about range and other Python functions, using Python's built-in help facilities.

3. How do I learn more about lists and other Python features?

Lists and the range() function are examples of powerful Python concepts that we can't cover comprehensively in this tutorial. How do you learn more about Python features? Here, we'll introduce you to the dir and help functions, which are built-in functions that document Python's features.

The dir function provides a list of features that apply to a list or any other Python variable, set, function, etc.. (Variables, sets, functions and so on are referred to as Python objects). Here is an example that uses dir on a list you've created
>>> a = [2, 3, 5, 10, 12]>>> dir(a)
This will produce a list in alphabetical order of "methods" --- functions ---- that apply to a. Now, you will see if you type this example that a very long list of methods is produced; there is no way you can understand what a particular method does just by the name. You can type the dir() function for any Python object, and get a list of methods that apply to it. To get help on any of the listed methods, type
To use a typical method, type
where <args> represents any arguments to the function.

To see help in action, type help(range) at the prompt.

Activity 3: Here's an example of discovering Python operations that apply to a given list within an interactive session. Look at the session excerpt below. We'll explain what's going on after we present the example, but try and understand what's happening as you read through it.
 >>> d = ['a', 'b', 'c', 'pi', 3.14, 2**0.5, 14]
 >>> dir(d)
 ['__add__', '__class__', '__contains__', '__delattr__', '__delitem__',
 '__delslice__', '__doc__', '__eq__', '__ge__', '__getattribute__',
 '__getitem__', '__getslice__', '__gt__', '__hash__', '__iadd__',
 '__imul__', '__init__', '__iter__', '__le__', '__len__', '__lt__',
 '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__',
 '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__',
 '__setslice__', '__str__', 'append', 'count', 'extend', 'index',
 'insert', 'pop', 'remove', 'reverse', 'sort']
 >>> help(d.append)
 Help on built-in function append:
 L.append(object) -- append object to end
 >>> d.append(15)
 >>> d
 ['a', 'b', 'c', 'pi', 3.1400000000000001, 1.4142135623730951, 14, 15]
 >>> help(d.sort)
 Help on built-in function sort:
 L.sort(cmp=None, key=None, reverse=False) -- stable sort *IN PLACE*;
 cmp(x, y) -> -1, 0, 1
 >>> d.sort()
 >>> d
 [1.4142135623730951, 3.1400000000000001, 14, 15, 'a', 'b', 'c', 'pi']

Here's what happens:
  1. We start by creating a list of strings and numbers d .
  2. We then ask what kind of operations can be applied to d ( dir(d) ). The result is a list of methods; for now we'll ignore the ones that are marked by double underscores like add ; and use the standard methods such as pop .
  3. We see that there is a function ("method") called append , and ask for help on this method ( help(d.append) ).
  4. We then append the number 15 to d ( d.append(15) ), and print out the new d , which has 15 tagged on the end.
  5. We then ask for help on the sort function ( help(d.sort) ).
  6. We then sort d using d.sort() , and print out the new d . Notice that numbers and strings are sorted in a particular order that Python uses by convention. In this convention, numbers always come before strings, so the number 15 comes before the string 'a' in the sorted list.

4. The for loop

We introduced previously in Part 3 the idea of a while loop, which was a loop that continues executing as long as a condition is True. The for loop is another kind of loop that iterates over values in a list. This is best explained by example:
#Create a list from 0 to 9
a = range(10)
print "a is ", a
#Iterate over the values in "a"
for val in a:
    #As for previous statements (if, while, etc.) the blocks are denoted by indentation.
    print "The current value is ", val
    if val>5:
        print "This value is greater than 5"
        print "The square of this value is", val**2
print "Done."

We will be making a great deal of use of the array structures found in the numpy package. These arrays are used in VPython, matplotlib, and scipy. They are a type of list that you can use for doing common numerical and matrix calculations. To created numpy arrays, we first need to import the numpy module as follows
 from numpy import *
Activity 4: Do the following:
  • In the Python shell, type the from numpy import * command shown above.
  • Then enter the following commands one at a time and examine the output:
>>> a = array([0,10,20,30,40])
>>> a
>>> a[:]
>>> a[1:3]
>>> a[1] = 15
>>> a
>>> b = arange(-5, 5, 0.5)
>>> b
>>> b ** 2
>>> 1/b
The output from the session can be found here:
Now do the following:

  • Look carefully at the output of the arange command, and make sure you understand it. To get more explanation on arange , type help(arange) .
  • Notice that operations on numpy arrays act on each element in the array. So b has the effect of raising to the power of two each element in the array.
  • Notice that the divide by zero in the 1/b command results in an "Inf" output.
  • You can practice further with numpy arrays. For example, create another array c=0.5*b , and then type b + c. Notice that for numpy arrays, b + c is not a concatenation of two lists, as in our previous discussion of lists, but the sum of the elements of b and c. ( This example shows how Python interprets operators like + in the context of the operands, i.e. the objects that are involved in the operation. This reflects the object oriented character of Python.)

Activity 5: To further practice using numpy arrays, do the following example:

  • Suppose an object under the influence of gravity and resistive drag falls with a downward velocity

  • where s_t = 20 m/s is the terminal speed and tau = 5 s is a time constant.

  • Write a program to write the acceleration and position of the object every half second for 20 seconds. Assume the initial position x(0)=0. (We will use this example to illustrate a few other ideas after we're done.)
  • We first find analytic expressions for the position and acceleration. Given the velocity, the position and acceleration are obtained from integration and differentiation by:

  • Our script imports numpy and defines a time array t with the following line:
  • t = arange(0,20.5,0.5) 
  • Another standard trick is to create a for loop that will run over an index that extends from the beginning to the end of an array. For example, to create a code that prints the elements of t[:] , we write
    for j in range(len(t)): print t[j]
  • To make sure you understand the previous line code example: len(t) is the length of the array t , which is 41. range(len(t)) is an array of integers [0, 1, 2 ..., 39, 40] .The for header creates a variable j that iterates over range(len(t)). In the body of the loop, t[j] is the j th value of t.
  • Now go ahead and produce a solution on your own, then check your answer against this script: . The output of this script can be found here: .

To finish off this tutorial, let's do some simple plotting using the matplotlib module of python. Both numpy and matplotlib can be imported using the pylab module, so we start by importing that. We will then define a time array and couple of trigonometric functions of time.
#import pylab
from pylab import *
#define a time array. This array runs starts from 0, runs in increments of pi/100, and stops at 4*pi-pi/100.
t = arange(0, 4*pi, pi/100)
#define an array that represents the sine of t
sin_t = sin(t)
#define an array that represents the cosine of t
cos_t = cos(t)
#Use the matplotlib plot function to plot both cos(t) and sin(t)
plot(t, sin(t),t, cos(t))
#add a title
title('sin and cosine')
#add a label on the x axis
xlabel('Time (s)')
#add a label on the y axis
ylabel('sin(t), cos(t)')
#create a legend displaying the functions
legend(('sin(t)', 'cos(t)'))
#always include this line at the end of any matplotlib script, or you won't see the plotting window

Activity 6: Do the following:

  • Copy and paste the preceding code into a new file, and run it. Close the plotting window; this typically restarts the Python session in the Python shell.
  • The previous example introduced several new functions: plot , title , xlabel , etc.. Find out more about these functions by importing pylab again and typing help(plot) , help(title) , etc.. in the Python Shell. We will explore these functions in more detail in the Learning Physics with Pylab tutorial (optional for first year students, required for second year students).

Warning on using pylab and visual together: a single script that uses both visual plotting routines (e.g. sphere() ) and pylab plotting routines (e.g. plot() ) will typically hang, because of well-known incompatibilities. However, there is no problem with running a script with calls from one of visual or pylab followed by a script with calls from another. You can use all numpy features in either pylab or visual .

This concludes the part 4 of the tutorial. In summary:
  1. We have learned about lists like a=[1,2,3,4] and numpy arrays, and what kind of operations can be done on them.
  2. We have learned how to explore possible actions on an object with dir(my_object) and help(my_object.method)
  3. We have learned about for loops, which iterate over a list.
  4. We have begun to visualize physical systems with visual and plot data with pylab .

We have also discussed a few examples of problem solving. The strategy we use is to
  1. Come up with some clearly written formulas that you want to code up on a computer.
  2. Include a lot of comments in the code.
  3. Include helpful hints on input (like descriptive prompts) and on output.

We hope that this tutorial has helped start you on the path to doing physics with computers. Please speak to your instructor if you have any suggestions for how to improve this tutorial.

First year physics students in PHY131/151 should now proceed to Physics with VPython.
Second year students in PHY224/254 should now proceed to Learning Physics with Pylab .

This concludes part 4 of the tutorial.