2012 March 30,

CS 111: Introduction to Python, Part C

Carleton College, Spring 2012

Prof. Joshua R. Davis, , Goodsell 106B, x4473

Lists

At the end of the preceding part of this tutorial, we learned about for loops, and we discovered that range(3, 12, 2) is a new type of object called a list. In this section we learn the basics of this useful data type.

A list is a sequence of objects of any type: integers, floating-point numbers, Booleans, strings, or anything else in Python. You enter a list using square brackets [] and commas, as seen below. Many of the basic operations for strings also work on lists, in a similar way. Try these commands in the interactive Python interpreter.

friendList = ["Jane", "Moon Unit", 2.718, "Babatope"]

friendList

type(friendList)

friendList[0]

friendList[1]

friendList[1:2]

len(friendList)

enemyList = ["Daniel Schorr", "Barney Gumble"]

friendList + enemyList

You can alter the contents of a list, by setting any list element to a new value:

a = [7, 2, 9, "Mary Jo", -62.2]

a[2] = "Ken doll"

a

Question A: What happens if you try to alter the contents of a string in this way?

Question B: Write a program that starts with a list of numbers, and uses a loop (either while or for) to replace each number with its square and then print the list. For example, if the first line of the program is l = [2, -2.3, 17, 1], then the program changes l to [4, 5.29, 289, 1] and prints it out.

The elements of a list can be Python objects of any type, including lists. Check this out:

myList = [[1, 9, -2], [2, 4, 11], [12, -98, 1]]

myList[1]

type(myList[1])

myList[0]

myList[0][1]

type(myList[0][1])

myList[2] = 13

myList

myList[0][2] = myList[0][2] + myList[2]

myList

Do you understand what happened in the fifth line there? The code myList[0][1] first asks myList for its 0th element; the answer is a list; it asks that list for its 1th element, which is the integer 9. Make sense? The same construction is used in the ninth line.

Now we come to extreme danger (or what counts for extreme danger, to a computer programmer). Consider:

list2 = [2, 7, 1, 3]

list3 = list2

list3[2] = 17

list3

Question C: What is list2, at the end of those commands?

Remember that a variable is essentially a spot in the computer's memory, where you can store a value. You can name your variables however you like, and store whatever you like in them. In this case, we stored a list in the variable list2. Then we made a new variable, list3, and set it to have the same value as list2. When we changed the contents of the list list3, the value of the list list2 also changed, because list3 and list2 refer to the same spot in the computer's memory. When you alter one of them, you automatically alter the other. This problem is called aliasing. (Just as a criminal can have multiple names, called aliases, so can a spot in a computer's memory.) Aliasing can cause serious errors that are difficult to find. We'll discuss how to avoid these errors later.

This next question is about the game Tic Tac Toe. This game is played on a 3x3 board. Each space on the board is either empty, or contains an X, or contains an O. If any row, column, or diagonal contains three Xs, then the X player wins; if any row, column, or diagonal contains three Os, then the O player wins. It never happens, that both players have won at the same time. (There are other rules of course, but they aren't relevant to my question.) We can represent a Tic Tac Toe board in Python as a list containing three lists, where each of these is a list of three strings, and each string is either "X", "O", or " ". For example, here is a board in which the O player has won:

b = [["O", "X", "X"], [" ", "O", " "], [" ", "X", "O"]]

It helps if you write the three sublists on top of each other, like a 3x3 grid. Then you will see that O has a diagonal. The Xs are at b[0][1], b[0][2], and b[2][1], right?

Question D: Write a program that starts with a Tic Tac Toe board, as just described, and prints out a message saying that X has won, that O has won, or that neither has won. Of course, your program should work on any valid Tic Tac Toe board, not just the one shown. I'm not psychic, but I see if statements in your future.

Built-In Functions

Python offers many handy operations on lists. Here are a few:

new_list = [4, 6.2, 1, -9]

max(new_list)

min(new_list)

sum(new_list)

If you ask Python for the type of any of these operations — for example, type(max) — you'll learn that they are functions. A function is a piece of Python code that takes in some input, does some computation with it, and produces some output. For example, max takes one input, namely a list of numbers. It does some computation, namely finding the greatest number in the list. (How does it do this? I don't know, and I don't care. I don't need to know how the function works, to know what it does and to use it effectively.) Then it produces one output, namely that greatest number it found.

This function concept comes directly from mathematics. In fact, Python comes with a variety of math functions built-in. Here's how you access some of them:

import math

math.sqrt(2.0) / 2.0

math.sin(math.pi / 4.0)

math.log(100.0)

math

type(math)

In the code above, the import math command loads the module called math module. A module, like a program, is simply a bunch of Python code. However, while a program is designed to accomplish a particular task, a module is more like a toolbox, consisting of various independent pieces of code, that can be used to help other programs. There are hundreds or maybe thousands of modules available for Python, written by various people around the world. Some come with the Python interpreter; others have to be downloaded and installed — which is sometimes easy and sometimes difficult.

Question E: What are the types of math.sin(0.0) and math.sin? Does the answer make sense?

User-Defined Functions

In the preceding section, we caught our first glimpse of functions. In this section, we learn how to write our own functions. After if statements, writing functions is the next huge step toward creating interesting programs.

To develop this concept, let's revisit our friend Paul from the previous tutorial. Your Paul code might have been like this:

n = 5
if n % 2 == 0:
    answer = n / 2
else:
    answer = n * 3 + 1
print answer

This code is in three parts. The first part, number = 5, is the input section; this is where you input the number, that you'd like Paul to respond to. The second part, consisting of the four lines of the if statement, are the guts of the code, where the computation gets done. The third part, print answer, is the output section; this is where the result of the computation is outputted to the user. When the input number is 5, the output number is 16. When the input number is 24, the output number is 12.

We're going to re-write this Paul code as a function, that takes a single number as input, and does the required computation, and produces the correct number as output. Here's the code:

def paul(n):
    if n % 2 == 0:
        answer = n / 2
    else:
        answer = n * 3 + 1
    return answer

Let me explain. The first line starts defining (def) a new function called paul. The function takes a single input, which is called n. The function carries out the if statement on the input n, and returns the contents of the answer variable as its output. Notice that the entire body of the function is indented relative to the def statement, much like the body of a while loop (or for loop, or if statement) is indented.

Once we have defined the function paul using the def statement, we can use that function as many times as we want. In TextWrangler, type the function definition above, and the code below, into a single program file. Run the program.

print paul(5)
print paul(24)
print type(paul(24))
print type(paul)

It's important to emphasize the distinction between returning a value and printing a value. The function paul does not print anything; it doesn't have any print statements, right? Instead, it merely reports an answer. The user of the function (who may be you, or your partner, or the grader, or me, or you-a-month-from-now-when-you-no-longer-remember-the-code, or someone else) may choose to print that answer, as in print paul(5). On the other hand, perhaps the user wants to see what three repetitions of the paul function does to the number 5. Then he might do this:

print paul(paul(paul(5)))

Or maybe the user wants to play out an entire game between me and Paul, listing everything that I would say in such a game. Here's some code:

n = 5
print "Me:", n
while n > 1:
    n = paul(n)
    print "Me:", n

The user couldn't accomplish either of these tasks, if paul printed out the answer instead of returning it. Returning an answer lets it be used in subsequent code; printing an answer shows it to the user, but doesn't let it be used in subsequent code.

In the paul code above, the variables n and answer are "dummy variables". The person writing the function can change these variable names as she likes, without changing the meaning or effect of the function, as long as she is consistent. For example, the following version of the paul function works exactly the same as the one above.

def paul(whatPaulHears):
    if whatPaulHears % 2 == 0:
        whatPaulSays = whatPaulHears / 2
    else:
        whatPaulSays = whatPaulHears * 3 + 1
    return whatPaulSays

Here is another example of functions, going back to part A of this tutorial. These two functions convert temperatures between the Fahrenheit and Celsius scales:

def fahrenheit(celsius):
    return 1.8 * celsius + 32.0

def celsius(fahr):
    return (fahr - 32.0) / 1.8

print fahrenheit(100.0)
print celsius(451.0)
print fahrenheit(celsius(98.6))

Question F: Write a function called gameLength, that takes as input a positive integer, and returns the game length for the Paul game started with that integer. (Game length was defined in the previous tutorial. It's the number of things that I say, in a game with Paul.) Your gameLength function must call upon the paul function. Therefore your program will have to include the definition of the paul function.

Golden Rules of Programming

Do you remember the Golden Rule of Programming, from part A of this tutorial? I hope so; it's really important. Let me reiterate it here, and add a second part.

First Golden Rule: In any computer code that you write, you must know the type of every variable.

Second Golden Rule: In any computer code that you write, you must know the input types and output type of every function.

Frequently, when a student asks me for help with his program, my immediate response is to point to a particular spot in the program and ask, "What is the type of this thing?" Frequently, the student's problem arises because the student is wrong about the type of some variable. For example, he thinks that he's adding two floats, but he's really adding a float to a string.

Frequently, a variable gets its value from a function, so the variable's type is the function's output type, so you need to know the function's output type to figure out the variable's type. If you can't figure out what the type of a variable is in your program, then add a print statement to print out the type() of the variable.