You have probably used computers to do all sorts of useful and interesting things. In each application, the computer responds in different ways to your input, from the keyboard, mouse or a file. Still the underlying operations are determined by the design of the program you are given. In this set of tutorials you will learn to write your own computer programs, so you can give the computer instructions to react in the way you want.
First let us place Python programming in the context of the computer hardware. At the lowest level in the computer there are instructions built into the hardware. These are very simple instructions, peculiar to the hardware of your particular type of computer. The instructions are designed to be simple for the hardware to execute, not for humans to follow. The earliest programming was done with such instructions. If was difficult and error-prone. A major advance was the development of higher-level languages and translators for them. Higher-level languages allow computer programmers to write instructions in a format that is easier for humans to understand. For example
z = x+y
is an instruction in many high-level languages that means something like:
No computer understands the high-level instruction directly; it is not in machine language. A special program must first translate instructions like this one into machine language. This one high-level instruction might be translated into a sequence of three machine language instructions corresponding to the three step description above:
0000010010000001
0000000010000010
0000010110000011
Obviously high-level languages were a great advance in clarity!
If you follow a broad introduction to computing, you will learn more about the layers that connect low-level digital computer circuits to high-level languages.
There are many high-level languages. The language you will be learning is Python. Python is one of the easiest languages to learn and use, while at the same time being very powerful: It is used by many of the most highly productive professional programmers. A few of the places that use Python extensively are Google, the New York Stock Exchange, Industrial Light and Magic, .... Also Python is a free language! If you have your own computer, you can download it from the Internet....
If you are not sure whether your computer already has Python, continue to Section 1.2.2, and give it a try. If it works, you are all set.
If you do need a copy of Python, go to the Downloads page linked to http://www.python.org. Be careful to choose the version for your operating system and hardware.
You just need to execute the installer, and interact enough to agree to all the default choices. Python works in Windows as well as on Apples and in the free operating system Linux. The latest stable version is 2.5.
Double-click on the installer. Find and run the MacPython.mpkg that is inside. Follow the defaults for installation.
Python is generally installed, though Idle is not always installed. Look for something like 'idle-python' (the name in the Ubuntu distribution).
Although Python is a high-level language, it is not English or some other natural human language. The Python translator does not understand “add the numbers two and three”. Python is a formal language with its own specific rules and formats, which these tutorials will introduce gradually, at a pace intended for a beginner. These tutorials are also appropriate for beginners because they gradually introduce fundamental logical programming skills. Learning these skills will allow you to much more easily program in other languages besides Python. Some of the skills you will learn are
Guiding Principals for the Hands-on Python Tutorials:
Although this approach is an effective way to introduce material, it is not so good for reference. Referencing is addressed in several ways:
Some people learn better visually and verbally from the very beginning. Some parts of the tutorial will also have links to corresponding flash video segments. Many people will find reading faster and more effective, but the video segments may be particularly useful where a computer interface can be not only explained but actually demonstrated. The links to such segments will be labeled. They will need a broadband link or a CD (not yet generated).
In the Firefox browser, the incremental find is excellent, and particularly useful with the single web page version of the tutorials. (It only fails to search footnotes.) It is particularly easy to jump through different sections in a form like 1.2.4.
First you need to set up a location to store your work and the example programs from this tutorial. If you are on a Windows computer, follow just one of the three choices below to find an appropriate place to download the example archive examples.zip, and then follow the later instructions to unzip the archive.
In Windows, after you have chosen a location for the archive, examples.zip, download it by right clicking on http://cs.luc.edu/anh/python/hands-on/examples.zip and selecting “Save As” or the equivalent on your browser and then navigate to save the archive to the chosen location on your computer.
Once you have the archive, open a file browser window for that directory, right click on examples.zip, select Extract All. This will create the folder examples. End up with a file browser window showing the contents of the examples folder. This will be your Python folder in later discussion.
Caution 1: On Windows, files in a zip archive can be viewed while they are still in the zip archive. Modifying and adding files is not so transparent. Be sure that you unzip the archive and work from the regular directory that holds the resulting unzipped files.
Caution 2: Make sure that all the directories leading down to your Python examples directory do not include any spaces in them. This will be important in Chapter 4 for the local webserver. In particular, that means you should not place your folder under “My Documents”. A directory like C:\hands-on or C:\python would be fine.
You also have the option of downloading
The disadvantage of a local copy is that the tutorial may be updated online after you get your download. The change log file http://www.cs.luc.edu/~anh/python/hands-on/changelog.html will show when the latest update was made and a summary of any major changes.
This section assumes Python is already on your computer. Windows does not come with Python. (To load Python see Section 1.1.2) On a Mac or Linux computer enough of Python comes installed to be able to run the sample program.
Before getting to the individual details of Python, you will run a simple text-based sample program. Find madlib.py in your Python folder (Section 1.2.1).
Options for running the program:
python madlib.py
The latter approach only works in a Windows command window if your operating system execution path is set up to find Python.
In whatever manner you start the program, run it, responding to the prompts on the screen. Be sure to press the enter key at the end of each response requested from you.
Try the program a second time and make different responses.
If you want to get right to the detailed explanations of writing your own Python, you can skip to the next section 1.2.4. If you would like an overview of a working program, even if all the explanations do not make total sense yet, read on.
Here is the text of the madlib.py program, followed by line-by-line explanations. The numbers on the right are not part of the program file. They are added for reference in the comments below.
""" 1
String Substitution for a Mad Lib 2
Adapted from code by Kirby Urner 3
""" 4
5
story = """ 6
Once upon a time, deep in an ancient jungle, 7
there lived a %(animal)s. This %(animal)s 8
liked to eat %(food)s, but the jungle had 9
very little %(food)s to offer. One day, an 10
explorer found the %(animal)s and discovered 11
it liked %(food)s. The explorer took the 12
%(animal)s back to %(city)s, where it could 13
eat as much %(food)s as it wanted. However, 14
the %(animal)s became homesick, so the 15
explorer brought it back to the jungle, 16
leaving a large supply of %(food)s. 17
18
The End 19
""" 20
21
def tellStory(): 22
userPicks = dict() 23
addPick('animal', userPicks) 24
addPick('food', userPicks) 25
addPick('city', userPicks) 26
print story % userPicks 27
28
def addPick(cue, dictionary): 29
prompt = "Enter a specific example for %s: " % cue 30
dictionary[cue] = raw_input(prompt) 31
32
tellStory() 33
raw_input("Press Enter to end the program.") 34
Line By Line Explanation
""" 1
String Substitution for a Mad Lib 2
Adapted from code by Kirby Urner 3
""" 4
There is multi-line text enclosed in triple quotes. Quoted text is called a string. A string at the very beginning of a file like this is documentation for the file.
Blank lines are included for human readability to separate logical parts. The computer ignores the blank lines.
story = """ 6
Once upon a time, deep in an ancient jungle, 7
there lived a %(animal)s. This %(animal)s 8
liked to eat %(food)s, but the jungle had 9
very little %(food)s to offer. One day, an 10
explorer found the %(animal)s and discovered 11
it liked %(food)s. The explorer took the 12
%(animal)s back to %(city)s, where it could 13
eat as much %(food)s as it wanted. However, 14
the %(animal)s became homesick, so the 15
explorer brought it back to the jungle, 16
leaving a large supply of %(food)s. 17
18
The End 19
""" 20
The equal sign tells the computer that this is an assignment statement. The computer will now associate the value of the expression between the triple quotes, a multi-line string, with the name on the left, story.
These lines contain the body of the string and the ending triple quotes. This story string is different from the documentation string of lines 1-4. It has a special form, called a format string. It will be used later to provide a format into which substitutions are made. The parts of the string starting with % and ending with s are places a substitute string will be inserted later. The substituted string will come from a custom dictionary that will contain the user's definitions of these words. The words in the parentheses: (animal), (food), (city), indicate that "animal", "food", and "city" are words in a dictionary. This custom dictionary will be created in the program and contain the user's definitions of these words. These user's definitions will be substituted later in the format string where each %(...)s is currently.
def tellStory(): 22
userPicks = dict() 23
addPick('animal', userPicks) 24
addPick('food', userPicks) 25
addPick('city', userPicks) 26
print story % userPicks 27
def is short for def inition. This line is the heading of a def inition, which makes the name tellStory becomes def ined as a short way to refer to the sequence of statements that start indented on line 23, and continue through line 27.
The equal sign tells the computer that this is another assignment statement. The computer will now associate the name userPicks with a new empty dictionary created by the Python code dict().
addPick is the name for a sequence of instructions defined on lines 29-31 for adding another definition to a dictionary, based on the user's input. The result of these three lines is to add definitions for each of the three words 'animal', 'food', and 'city' to the dictionary called userPicks.
This is where all the work becomes visible: Print the story format string with substitutions from the dictionary userPicks, to give the user's customized story. The '%' here is an operator on the string story that essentially means 'with substitutions from'.
def addPick(cue, dictionary): 29
prompt = "Enter a specific example for %s: " % cue 30
dictionary[cue] = raw_input(prompt) 31
This line is the heading of a definition, which gives the name addPick as a short way to refer to the sequence of statements indented on line 30 and line 31. addPick is followed by two words in parenthesis, cue and dictionary. These two words are associated with an actual cue word and dictionary given when this definition is invoked in lines 24-26.
On the right side of the equal sign is an expression involving a format string, much simpler than story. The resulting string just has the current value of cue substituted for the %s. This resulting string is then given the name prompt.
The right-hand-side of this equal sign causes an interaction with the user. The prompt string is printed to the computer screen, and the computer waits for the user to enter a line of text. That line of text then becomes a string inside the program. The left-hand-side of the equal sign is a reference to the definition of the cue word in the dictionary. The whole line ends up making the definition of the current cue word become the string typed by the user.
tellStory() 33
raw_input("Press Enter to end the program.") 34
The definition of tellStory above does not make the computer do anything besides remember what the instruction tellStory means. It is only in this line, with the name, tellStory, followed by parentheses, that the whole sequence of remembered instructions are actually carried out.
This line is only here to accommodate running the program in Windows by double clicking on its file icon. Without this line, the story would be displayed and then the program would end, and Windows would make it immediately disappear from the screen! This line forces the program to continue being displayed until there is another response from the user, and meanwhile the user may look at the output from tellStory.
The program that translates Python instructions and then executes them is the Python interpreter.
This interpreter is embedded in a number of larger programs that make it particularly easy to develop Python programs. Such a programming environment is Idle, and it is a part of the standard distribution of Python.
Read the section that follows for your operating system:
(Assuming you already have Python installed.) Display your Python folder. You should see icon for Idle25Shortcut (and maybe a similar icon with a number different than 25 - ignore any other unless you know you are using that version of Python). Double click on the appropriate shortcut, and an Idle window should appear. After this the instructions are the same in any operating environment. It is important to start Idle through these in several circumstances. It is best if it you make it a habit to use this shortcut. For example the alternative of opening an existing Python program in Windows XP or Vista from Open With Idle in the context menu looks like it works at first but then fails miserably but inexplicably when you try to run a graphics program.
the new version of Python and Idle should be in a folder called MacPython 2.5, inside the Applications folder. It is best if you can open a terminal window, change into your Python folder from Section 1.2.1, and enter the command
idle
If the command is not recognized, you may need to include the full path to the idle program.
The approach depends on the installation. In Ubuntu, you should fine idle in the Programming section of the Applications menu. As with OS X above, you are better starting idle from a terminal, with the current directory being your Python folder.
Idle has several parts you may choose to display, each with its own window. Depending on the configuration, Idle can start up showing either of two windows, an Edit Window or a Python Shell Window. You are likely to first see an Edit window, whose top left corner looks something like in Windows:
For more on the Edit Window, see Section1.9.
If you see this Edit Window with its Run menu on top, go to the Run menu and choose PYTHON SHELL to open a Python Shell Window for now. Then you may close the Edit Window.
Either initially, or after explicitly opening it, you should now see the Python Shell window, with a menu like the following, though the text may be slightly different:
Look at the Python Shell. ...
In the Shell the last line should look like
>>>
The >>> is the prompt, telling you Idle is waiting for you to type something. Continuing on the same line enter
6+3
Be sure to end with the Enter key. After the Shell responds, you should see something like
>>> 6+3
9
>>>
The shell evaluates the line you entered, and prints the result. You see Python does arithmetic. At the end you see a further prompt >>> where you can enter your next line.... The result line, showing 9, that is produced by the computer, does not start with “> > >”.
Python directly recognizes a variety of types of data. Here are a few:
3, 6, -7, 1.25
'hello', 'The answer is: '
[1, 2, 3, 4], ['yes', 'no', 'maybe']
None
Python has large collection of built-in functions that operate on different kinds of data to produce all kinds of results. To make a function do its action, parentheses are required. These parentheses surround the parameter or parameters, as in a function in algebra class.
The general syntax to execute a function is
functionName ( parameters )
One function is called type, and it returns the type of any object. The Python Shell will evaluate functions. In the Shell the last line should look like
>>>
Continuing on the same line enter
type(7)
Always remember to end with the Enter key. After the Shell responds, you should see something like
>>> type(7)
<type 'int'>
>>>
In the result, int is short for integer. At the end you see a further prompt where you can enter your next line....
For the rest of this section, at the >>> prompt in the Python Shell, individually enter each line below that is set off in typewriter font. So next enter
type(1.25)
Note the name in the last result is float, not real or decimal, coming from the term “floating point”, for reasons that will be explained later, in Section 1.14.1. Enter
type('hello')
In your last result you see another abbreviation: str rather than string. Enter
type([1, 2, 3])
Strings and lists are both sequences of parts (characters or elements). We can find the length of that sequence with another function with the abbreviated name len. Try both of the following, separately, in the Shell:
len([2, 4, 6])
len('abcd')
Some functions have no parameters, so nothing goes between the parentheses. For example, some types serve as no-parameter functions to create a simple value of their type. Try
list()
You see the way an empty list is displayed.
Functions may also take more than one parameter. Try
max(5, 11, 2)
Above, max is short for maximum.
Some of the names of types serve as conversion functions (where there is an obvious meaning for the conversion). Try each of the following, one at a time, in the Shell:
str(23)
int('125')
An often handy Shell feature: an earlier Shell line may to copied and edited by clicking anywhere in the previously displayed line and then pressing Enter. For instance you should have entered several lines starting with len. click on any one, press Enter, and edit the line for a different test.
We start with the integers and integer arithmetic, not because arithmetic is exciting, but because the symbolism should be mostly familiar. Of course arithmetic is important in many cases, but Python is probably more often used to manipulate text and other sorts of data, as in the sample program in Section 1.2.2.
Python understands numbers and standard arithmetic. For the whole section on integer arithmetic, where you see a set-off line in typewriter font, type individual lines at the > > > prompt in the Python Shell. Press Enter after each line to get Python to respond:
77
2 + 3
5 - 7
Python should evaluate and print back the value of each expression. Of course the first one does not require any calculation. It appears the shell just echoes back what you printed. Do note that the line with the value produced by the shell does not start with > > > and appears at the left margin. Hence you can distinguish what you type (after the “> > >” prompt) from what the computer responds.
The Python Shell is an interactive interpreter. As you can see, after you press Enter, it is evaluating the expression you typed in, and then printing the result automatically. This is a very handy environment to check out simple Python syntax and get instant feedback. For more elaborate programs that you want to save, we will switch to an Editor Window later.
Try in the Shell:
2 x 3
You should get your first syntax error. The 'x' should have become highlighted, indicating the location where the Python interpreter discovered that it cannot understand you: Python does not use x for multiplication as you may have done in grade school. The x can be confused with the use of x as a variable (more on that later). Instead the symbol for multiplication is an asterisk '*'. Enter each of the following. You may include spaces or not. The Python interpreter can figure out what you mean either way. Try in the Shell:
2*5
2 + 3 * 4
If you expected the last answer to be 20, think again: Python uses the normal precedence of arithmetic operations: Multiplications and divisions are done before addition and subtraction, unless there are parentheses. Try
(2+3)*4
2 * (4 - 1)
Now try the following in the Shell, exactly as written followed by Enter, with no closing parenthesis:
5 * (2 + 3
Look carefully. There is no answer given at the left margin of the next line and no prompt > > > to start a new expression. If you are using Idle, the cursor has gone to the next line and has only indented slightly. Python is waiting for you to finish your expression. It is smart enough to know that opening parentheses are always followed by the same number of closing parentheses. The cursor is on a continuation line. Type just the matching close-parenthesis and Enter,
)
and you should finally see the expression evaluated. (In some versions of the Python interpreter, the interpreter puts '...' at the beginning of a continuation line, rather than just indenting.)
Negation also works. Try in the Shell:
-(2 + 3)
If you think about it, you learned several ways to do division. In the earliest grades you would say “14 divided by 4 is 3 with a remainder of 2”. The problem here is that the answer is in two parts, the integer quotient 3 and the remainder 2. Python has separate operations to generate each part. Python uses the common division symbol / for the operation that produces just the quotient, and introduces the symbol % for the operation of finding the remainder. Try each in the Shell
14/4
14%4
Now predict and then try each of
23/5
23%5
20%5
6/8
6%8
Finding remainders will prove more useful than you might think in the future.
Of course as you moved on in school, you learned that 6/8 is also 0.75. To get that sort of result in Python, you need decimal notation, which brings in extra complications in Section 1.14.1
Enough with numbers for a while. Strings of characters are another important type in Python.
A string in Python is a sequence of characters. For Python to recognize a sequence of characters, like hello, as a string, it must be enclosed in quotes to delimit the string.
For this whole section on strings, continue trying each set-off line of code in the Shell. Try
"hello"
Note that the interpreter gives back the string with single quotes. Python does not care what system you use. Try
'Hi!'
Having the choice of delimiters can be handy.
Exercise 1.5.1.1. * Figure out how to give Python the string containing the text: I'm happy. Try it. If you got an error, try it with another type of quotes, and figure out why that one works and not the first.
There are many variations on delimiting strings and embedding special symbols. We will consider more ways later in Section 1.8.
A string can have any number of characters in it, including 0. The empty string is '' (two quote characters with nothing between them).
Strings are a new Python type. Try
type('dog')
type('7')
type(7)
The last two lines show how easily you can get confused! Strings can include any characters, including digits. Quotes turn even digits into strings. This will have consequences in the next section....
Strings also have operation symbols. Try in the Shell (noting the space after very):
'very ' + 'hot'
The plus operation with strings means concatenate the strings.
Think of the relation of addition and multiplication of integers, and then guess the meaning of
3*'very ' + 'hot'
Were you right? The ability to repeat yourself easily can be handy.
Exercise 1.5.2.1. * Figure out a compact way to get Python to make the string, “YesYesYesYesYes”, and try it. How about “MaybeMaybeMaybeYesYesYesYesYes” ? Hint: 1
Predict the following and then test. Remember the last section on types:
7+2
'7'+'2'
Python checks the types and interprets the plus symbol based on the type. Try
'7'+2
With mixed string and int types, Python sees an ambiguous expression, and does not guess which you want – it just gives an error! 2
Each set-off line in this section should be tried in the Shell.
Try
width = 10
Nothing is displayed by the interpreter after this entry, so it is not clear anything happened. Something has happened. This is an assignment statement, with a variable, width, on the left. A variable is a name for a value. An assignment statement associates a variable name on the left of the equal sign with the value of an expression calculated from the right of the equal sign. Enter
width
Once a variable is assigned a value, the variable can be used in place of that value. The response to the expression width is the same as if its value had been entered.
The interpreter does not print a value after an assignment statement because the value of the expression on the right is not lost. It can be recovered if you like, by entering the variable name and we did above.
Try each of the following lines:
height = 12
area = width * height
area
The equal sign is an unfortunate choice of symbol for assignment, since Python's usage is not the mathematical usage of the equal sign. If the symbol had appeared on keyboards in the early 1990's, it would probably have been used for assignment instead of =, emphasizing the asymmetry of assignment. In mathematics an equation is an assertion that both sides of the equal sign are already, in fact, equal. A Python assignment statement forces the variable on the left hand side to become associated with the value of the expression on the right side. The difference from the mathematical usage can be illustrated. Try:
10 = width
so this is not equivalent in Python to width = 10. The left hand side must be a variable, to which the assignment is made. Try
width = width + 5
This is, of course, nonsensical as mathematics, but it makes perfectly good sense as an assignment. Can you figure out the value that is now associated with width? Check by entering
width
In the assignment statement, the expression on the right is evaluated first. At that point width was associated with its original value 10, so width + 5 had the value of 10 + 5 which is 15. That value was then assigned to the variable on the left (width again) to give it a new value. We will modify the value of variables in a similar way routinely.
Assignment and variables work equally well with strings. Try:
first = 'Sue'
last = 'Wong'
name = first + ' ' + last
name
Try entering:
first = fred
Note the different form of the error message. The earlier errors in these tutorials were syntax errors: errors in translation of the instruction. In this last case the syntax was legal, so the interpreter went on to execute the instruction. Only then did it find the error described. There are no quotes around fred, so the interpreter assumed fred was an identifier, but the name fred was not defined at the time of execution.
It is easy to forget quotes where you need them and put them around a variable name that should not have them!
Try in the Shell:
fred = 'Frederick'
first = fred
first
Now fred, without the quotes, makes sense.
There are more subtleties to assignment and the idea of a variable being a “name for” a value, but we will worry about them later, in Section 2.4.6. They do not come up if our variables are just numbers and strings.
Autocompletion: A handy short cut. Python remembers all the variables you have defined at any moment. This is handy when editing. Without pressing Enter, type into the Shell just
f
Then hold down the Alt key and press the '/' key. This key combination is abbreviated Alt-/. You should see f autocompleted to be first. This is particularly useful if you have long identifiers! You can press Alt-/ several times if more than one identifier starts with the initial sequence of characters you typed. If you press Alt-/ again you should see fred. Backspace and edit so you have fi, and then and press Alt-/ again. You should not see fred this time, since it does not start with fi.
Expressions like 27 or 'hello' are called literals, coming from the fact that they literally mean exactly what they say. They are distinguished from variables, who value is not directly determined by their name.
The sequence of characters used to form a variable name (and names for other Python entities later) is called an identifier. It identifies a Python variable or other entity.
There are some restrictions on the character sequence that make up an identifier:
and del for is raise
assert elif from lambda return
break else global not try
class except if or while
continue exec import pass yield
def finally in print
There are also identifiers that are automatically defined in Python, and you could redefine, but you probably should not unless you really know what you are doing! When you start the editor, we will see how Idle uses color to help you know what identifies are predefined.
Python is case sensitive: The identifiers last, LAST, and LaSt are all different. Be sure to be consistent.
What is legal is distinct from what is conventional or good practice or recommended. Meaningful names for variables are important for the humans who are looking at programs, understanding them, and revising them. That sometimes means you would like to use a name that is more than one word long, like price at opening, but blanks are illegal! One poor option is just leaving out the blanks, like priceatopening. Then it may be hard to figure out where words split. Two practical options are
Use the choice that fits your taste (or the taste of the people you are working with).
In interactive use of the Python interpreter, you can type an expression and immediately see the result of its evaluation. This is fine to test out syntax and maybe do simple calculator calculations. In a program run from a file like the first sample program, Python does not display expressions this way. If you want your program to display something, you can give explicit instructions with a print statement. Try in the Shell:
x = 3
y = 5
print 'The sum of', x, 'plus', y, 'is', x+y
The print statement will prints as strings everything in a comma-separated sequence of expressions, and it will separate the results with single blanks. Note that you can mix types: anything that is not already a string is automatically converted to its string representation.
There are several other variations. Try these two in the Shell:
print 'Hi!'
print
You can print a single expression or no expressions. Each of the versions above advances to a new line. The last version with no parameters only advances to the next line. This is one way to leave a blank line in your output.
Strings delimited by one quote character are required to lie within a single Python line. It is sometimes convenient to have a multi-line string, which can be delimited with triple quotes: Try typing the following. You will get continuation lines until the closing triple quotes. Try in the Shell:
sillyTest = '''Say,
"I'm in!"
This is line 3'''
print sillyTest
The line structure is preserved in a multi-line string. As you can see, this also allows you to embed both single and double quote characters!
Continuing in the Shell with sillyTest, enter just
sillyTest
The answer looks strange! It indicates an alternate way to encode the string using escape codes. Escape codes are embedded inside string literals and start with a backslash character (\). They are used to embed characters that are either unprintable or have a special syntactic meaning to Python that you want to suppress. In this example you see the most common ones:
| Escape code | Meaning |
| \' | ' |
| \n | newline |
| \\ | \ |
The newline character indicates further text should appear on a new line. When you use a print statement, you get the actual printed meaning of the escaped coded character.
Predict the result, and try in the Shell:
print 'a\nb\n\nc'
Did you guess the right number of lines splitting in the right places?
It is time to put longer collections of instructions together. That is most easily done by creating a text file and running the Python interpreter on the file. Idle simplifies that process.
First you can put an existing file into an Idle Edit Window. Click on the Idle File menu and select Open. (Or as you see, you can use the shortcut Ctrl+O. That means holding down the Ctrl key, and pressing the letter O for Open.) You should get a file selection dialog. You should have the sample program madlib.py displayed in the list. Select it and open it. (If you do not see the program, then you either failed to download the example programs, Section 1.2.1, or you did not start Idle in the proper folder, Section 1.2.4.)
You will see the source code again. Now run this program from inside of Idle: Go to the Run menu of that Edit window, and select Run Module. Notice the shortcut (F5).
If the Shell window does not automatically come to the foreground, select it. You should see a line saying “RESTART” and then the start of the execution of the Mad Lib program with the cursor waiting for your entry after the first prompt. Finish executing the program. Be sure to type the final requested Enter, so you get back to the interpreter prompt: > > >
Look at the editor window again. You should see that different parts of the code have different colors. String literals are likely green. The reserved words def and print are likely orange. Look at the last two lines, where the identifier tellStory is black, and the identifier raw_input is likely purple. Only identifiers that are not predefined by Python are black. If you create an identifier name, make sure Idle shows it in black.
When you execute a program from the Idle Editor, the interpreter gives a banner saying “RESTART”, meaning that all the things you defined in any shell session so far are wiped clean and the program you are running starts fresh. There is one egregious exception to that, that was still present at least in the version of Idle for Python 2.5.1. We will try to demonstrate the bug. (A bug is an error in a program.)
Start running the Mad Lib program again by going to the Editor Window containing madlib.py, and start running the program again, but do not continue....
You should see a prompt for user input generated by the program. Ignore this prompt and go back to the Edit Window and start the Mad Lib program again.
If this bug is still present, you should see a difference in this restart: This time after the RESTART banner and the interpreter prompt: > > >, which looks innocent enough, but this program should show the program's prompt string for input.
The problem only comes up because you interrupted the last execution when user input was being waited for. The restart was not complete here: The system is still looking for the pending user input from the last execution.
The fix is simple: Make sure the Interpreter Window is the currently selected window, and press return to terminate the lost user input. In some circumstances, you may need to press return a second time.
After that the program should start up normally with its prompt.
Watch out for this behavior, and remember the fix.
Make sure you have Idle started in your Python directory (in Windows with the provided Idle shortcut link), where you will store program files. (Do not start Idle from the Windows Start Menu!) If you just started Idle now, you may already have a blank Edit Window in front of you. If not, open a new window by going to the File menu and selecting New Window. This gives you a rather conventional text editing window with the mouse available, ability to cut and paste, plus a few special options for Python.
Type (or paste) the following into the editor window:
print 'Hello world!'
Save the file with the File menu -> Save, and then enter the file name hello.py. Python program files should always be given a name ending in ".py", and you must enter the .py extension explicitly .
If you look in the editor, you should see that your text is color coded. The editor will color different parts of Python syntax in special colors. (In version 2.4 of Python, the coloring only happens after you save your file with the '.py' ending.)
Now that you have a complete, saved program, choose Run menu -> Run Module. You should see the program run in the Python Shell window.
You just wrote and executed a program. Unlike when you use the shell, this code is saved to a file in your Python folder. You can open and execute the file any time you want. (In Idle, use File->Open.)
To the interpreter, a program source file corresponds to a Python module. We will tend to use the more general term: a program file is a module. Note the term from the menu when running the program.
Distinguish program code from Shell text: It is easy to confuse the Shell and the Edit windows. Make sure you keep them straight. The hello.py program is just the line
print 'Hello world!'
that you typed into the edit window and saved. When you ran the program in Idle, you saw results in the Shell. First came the Restart notice, the one-line output from the program saying hello, and a further Shell prompt:
>>> ================================ RESTART ========
>>>
Hello world!
>>>
You could also have run this single print statement directly in the Shell in response to a Shell prompt. When you see >>>, you could enter the print statement and get the exchange between you and the Shell:
>>> print 'Hello world'
Hello world!
>>>
The three lines above are not a program you could save in a file and run. This is just an exchange in the Shell, with its >>> prompts, individual line to execute and the response. Again, just the single line statement, with no >>>,
print 'Hello world!'
entered into the Edit window forms a program you can save and run. We will shortly get to more interesting many-statement programs, where it is much more convenient to use the Edit window than the Shell!
The program above is self evident, and shows how short and direct a program can be (unlike other languages like Java). Still, right away, get used to documenting a program. Python has a special feature: If the beginning of a program is just a quoted string, that string is taken to be the program's documentation string. Open the example file hello2.py in the Edit window:
'''A very simple program,
showing how short a Python program can be!
Authors: ___, ___
'''
print 'Hello world!' #This is a stupid comment after the # mark
Most commonly, the initial documentation goes on for several lines, so a multi-line string delimiter is used (the triple quotes). Just for completeness of illustration in this program, another form of comment is also shown, a comment that starts with the symbol # and extends to the end of the line. The Python interpreter completely ignores this form of comment. Such a comment should only be included for better human understanding. Avoid making comments that do not really aid human understanding. (Do what I say, not what I did above.) Good introductory comment strings and appropriate names for the parts of your programs make the # symbol comments less needed.
Run the program and see the documentation and comment make no difference in the result.
Of course you can arrange the windows on your computer screen any way that you like. A suggestion as you start to use the combination of the editor to write, the shell to run, and the tutorial to follow along: Make all three mostly visible your computer screen at once. Drag the editor window to the upper left. Place the Shell window to the lower left, and perhaps reduce its height a bit so there is not much overlap. If you are looking at the web version of the tutorial on the screen, make it go top to bottom on the right, but not overlap the Idle windows too much. The web page rendering should generally adapt to the width pretty well. You can always temporarily maximize the window. Before resizing the browser window, it is good to look for an unusual phrase on your page, and search for it after resizing, since resizing can totally mess up your location in the web page.
There is an alternative to maximization for the Idle editor window: It you want it to go top to bottom of the screen but not widen, you can toggle that state with Alt-2. Play with all this.
The hello program of Section 1.9.3 always does the same thing. This is not very interesting. Programs are only going to be reused if they can act on a variety of data. One way to get data is directly from the user. Modify the hello.py program as follows in the editor, and save it from the File menu with Save As...., using the name hello_you.py.
person = raw_input('Enter your name: ')
print 'Hello', person
Run the program. In the Shell you should see
Enter your name:
Follow the instruction (and press Enter). Make sure the typing cursor is in the Shell window, at the end of this line. After you type your response, you can see that the program has taken in the line you typed. That is what the built-in function raw_input does: First it prints the string you give as a parameter (in this case 'Enter your name: '), and then it waits for a line to be typed in, and returns the string of characters you typed. In the hello_you.py program this value is assigned to the variable person, for use later.
The parameter inside the parentheses after raw_input is important. It is a prompt, prompting you that keyboard input is expected at that point, and hopefully indicating what is being requested. Without the prompt, the user would not know what was happening, and the computer would just sit there waiting!
Open the example program, interview.py. Before running it (with any made-up data), see if you can figure out what it will do:
'''Illustrate raw_input and print.'''
applicant = raw_input("Enter the applicant's name: ")
interviewer = raw_input("Enter the interviewer's name: ")
time = raw_input("Enter the appointment time: ")
print interviewer, "will interview", applicant, "at", time
The statements are executed in the order they appear in the text of the program: sequentially. This is the simplest way for the execution of the program to flow. You will see instructions later that alter that natural flow.
If we want to reload and modify the hello_you.py program to put an exclamation point at the end, you could try:
person = raw_input('Enter your name: ')
print 'Hello', person, '!'
Run it and you see that it is not spaced right. There should be no space after the person's name, but each field in a print statement is always separated by a space. There are several ways to fix this. You should know one. Think about it before going on to the next section. Hint: 3
One way to put punctuation after the person in hello_you.py is to use the plus operator. While we are at it, lets turn everything into one field. Note the space inside the end of the 'Hello ' string. Save as hello_you2.py:
person = raw_input('Enter your name: ')
print 'Hello ' + person + '!'
It is common to want to mix preset strings, like 'Hello ' and '!' interspersed with the values of one or more variables or expressions, like person.
One way to think of this is “fill in the blanks”, with a format like:
Hello _____!
where there are parts of the desired string that are fixed ('Hello ' and '!') and one or more places where
substitutions are to be made (in the 'blank'). If we want to ”'fill in the blank” with the value of the
variable person, which might refer to 'Sue', then the final string after filling in the blank would be
'Hello Sue!'.
Instead of a long underscore to indicate the “blank” in the example above, Python uses the special symbolism '%s' in the place where a substitution is to be made, so the format string in this case would be 'Hello %s!'. Filling in the blanks in a format string is an operation in Python with the operator % so the general syntax is:4
format_string % substitutions
The simplest way to illustrate this is in the Shell: First give person a value by typing into the Shell
person = 'Sue'
Then enter the format expression in the Shell:
'Hello %s!' % person
Now back to your hello_you2.py program. Add a line to print out the expression above:
person = raw_input('Enter your name: ')
print 'Hello ' + person + '!'
print 'Hello %s!' % person
then run it with any name and see that the last two lines do the same thing
This syntax is not too impressive in this situation with one substitution, but in fact many substitutions may be made. Consider the interview program. Suppose we want to add a period at the end of the sentence. One approach would be to combine everything with plus signs. Another way is with the format operator. Here the idea is to fill in the blanks in
_____ will interview _____ at _____.
Can you figure out what the Python syntax for the format string will be?
Run the example file interview2.py, and check that the results combining parts with the + operator match the result with the format string:
'''Compare print with concatenation and with format string.'''
applicant = raw_input("Enter the applicant's name: ")
interviewer = raw_input("Enter the interviewer's name: ")
time = raw_input("Enter the appointment time: ")
print interviewer + ' will interview ' + applicant + ' at ' + time +'.'
print '%s will interview %s at %s.' % (interviewer, applicant, time)
Each %s in the format string indicates a substitution, so there are three in all. The syntax with the format operator % after the format string allows just one further operand, while we have three substitutions to make. To convert the three values into a single object, they are put into a single tuple of values: a parentheses enclosed, comma separated sequence, (interviewer, applicant, time) in this case. The format operator substitutes values in the same order as they appear in the tuple. Always make sure your tuple includes the exact number of values required by the format string. A tuple is more human readable with space after the commas, but it does not matter to the interpreter.
Format strings with this sort of format match up with parameter values in order. There is another approach with a dictionary, that was used in the first sample program, and will be discussed more in Section 1.12.2 on dictionaries.
Predict the results of the example file lunch.py shown below,and then check yourself by running it:
'''Fancier format string example.'''
part1 = 'lunch'
part2 = 'box'
format = 'The words %s and %s can appear separately or together: %s%s.'
print format % (part1, part2, part1, part2)
Exercise 1.10.2.1. * Create a modified program lunch2.py, which extends the formatted print statement to print not only lunchbox, but also boxlunch. Hint: 5
In section 1.14.3 you will see another of the many options for format string substitutions. All the special codes for substitutions start with a '%'. This raises the question of what to do when you really want a '%' in the final formatted string! A final single '%' is generated by the special code '%%' in the format string. For instance the code
x = 90
print 'The result is %s%%.' % x
prints
The result is 90%.
Consider the following problem: Prompt the user for two numbers, and then print out a sentence stating the sum. For instance if the user entered 2 and 3, you would print “The sum of 2 and 3 is 5.”
You might imagine a solution like the example file addition1.py, shown below. There is a problem. Can you figure it out before you try it? Hint: 6 End up running it in any case.
x = raw_input("Enter a number: ")
y = raw_input("Enter a second number: ")
print 'The sum of %s and %s is %s.' % (x, y, x+y) # error!
We do not want string concatenation, but integer addition. We need integer operands. Briefly mentioned in Section 1.3 was the fact that we can use type names as functions to convert types. One approach would be to do that. Further variable names are also introduced in the example addition2.py file below to emphasize the distinctions in types:
'''Conversion of strings to int before addition'''
xString = raw_input("Enter a number: ")
x = int(xString)
yString = raw_input("Enter a second number: ")
y = int(yString)
print 'The sum of %s and %s is %s.' % (x, y, x+y)
This calculates x+y correctly, but you might wonder why it prints correctly, since the format specifiers, %s, are for strings, when we have just taken pains to generate integers! In fact, any type of object can be printed as some form of a string, and Python will convert automatically for a %s in a format string.
Run it to check.
We will see later in web pages and files that we will be given string versions of integers and want to convert to actual integers for arithmetic, so the idea above is important. On the other hand, in the situation of getting values directly from the keyboard, there is a simpler alternative....
You noticed the modifier “raw” in raw_input. There is also a version called input that processes the input as if you typed it into the shell as an expression to be evaluated, recognizing a number when it sees it, and translating and evaluating automatically. Try the variation in example file, addition3.py:
'''Two numeric inputs'''
x = input("Enter a number: ")
y = input("Enter a second number: ")
print 'The sum of %s and %s is %s.' % (x, y, x+y)
The prompt works the same way as with raw_input. This version is much more powerful than the version with the int conversion of strings. As in the shell, arbitrary expressions in the input are evaluated:
As a test, run the program entering the expressions 5-1 and 2*3.
See the code below. We introduced tuples for the string format operation. In many situations, including this situation with keyboard input, it is the commas that force the formation of a tuple. We could ask for two numbers to be entered together, comma separated, and the input function returns a tuple. The first statement below is written with the assumption that a tuple will be entered, because there is also a comma on the left-hand side of the assignment, creating a multiple assignment statement. The variables on the left associate with the values of the tuple parts on the right in order. Check out and run the example file addition4.py:
'''Two numeric inputs in one input statement'''
x, y = input("Enter two comma separated numbers: ")
print 'The sum of %s and %s is %s.' % (x, y, x+y)
Run it. If you enter the following at the prompt:
2, 3
the code should work. Then x gets the value 2 and y gets the value 3.
Exercise 1.10.4.1. * Write a version, add3.py, that asks for three numbers, and lists all three, and their sum, in similar format to the example above.You may use tuples or not, as you like (or try both).
Exercise 1.10.4.2. * Write a program, quotient.py, that prompts the user for two integers, and then prints them out in a sentence with an integer division problem like "The quotient of 14 and 3 is 4 with a remainder of 2". Review Section 1.4.3 if you forget the integer division or remainder operator.
The simple programs so far have followed a basic programming pattern: input-calculate-output. Get all the data first, calculate with it second, and output the results last. The pattern sequence would be even clearer if we explicitly create a named result variable in the middle:
x, y = input("Enter two comma separated numbers: ")
sum = x + y
print 'The sum of %s and %s is %s.' % (x, y, sum)
We will see more complicated patterns involving repetition in the future.
When new Python syntax is introduced, the usual approach will be to give both specific examples and general templates. In general templates for Python syntax the typeface indicates the the category of each part:
| Typeface | Meaning |
| Typewriter font | Text to be written verbatim |
| Emphasized | A place where you can use an arbitrary identifier. The emphasized text attempts to be descriptive of the meaning of the identifier in the current context. |
| Normal text | A description of what goes in that position, without giving explicit syntax |
We will use these conventions shortly in the discussion of function syntax, and will continue to use the conventions throughout the tutorial.
If you know it is the birthday of a friend, Emily, you might tell those gathered with you to sing "Happy Birthday to Emily".
We can make Python display the song. Read, and run if you like, the example program birthday1.py:
print "Happy Birthday to you!"
print "Happy Birthday to you!"
print "Happy Birthday, dear Emily."
print "Happy Birthday to you!"
You would probably not repeat the whole song to let others know what to sing. You would give a request to sing via a descriptive name like "Happy Birthday to Emily".
In Python we can also give a name like happyBirthdayEmily, and associate the name with whole song by using a function definition. We use the Python def keyword, short for define.
Read for now:
def happyBirthdayEmily():
print "Happy Birthday to you!"
print "Happy Birthday to you!"
print "Happy Birthday, dear Emily."
print "Happy Birthday to you!"
There are several parts of the syntax for a function definition to notice:
The heading contains def, the name of the function, parentheses, and finally a colon.
def function_name():
The remaining lines form the function body and are indented by a consistent amount. (The exact amount is not important to the interpreter, though 2 or 4 spaces are common conventions.)
The whole definition does just that: defines the meaning of the name happyBirthdayEmily, but it does not do anything else yet – for example, the definition itself does not make anything be printed yet. This is our first example of altering the order of execution of statements from the normal sequential order. This is important: the statements in the function definition are not executed as Python first passes over the lines.
The code above is in example file birthday2.py. Load it in Idle and execute it from there. Nothing should happen visibly. This is just like defining a variable: Python just remembers the function definition for future reference. After Idle finished executing a program, however, its version of the Shell remembers function definitions from the program.
In the Idle Shell (not the editor), enter
happyBirthdayEmily
The result probably surprises you! When you give the Shell an identifier, it tells you its value. Above, without parentheses, it identifies the function code as the value (and gives a location in memory of the code). Now try the name in the Idle Shell with parentheses added:
happyBirthdayEmily()
The parentheses tell Python to execute the named function rather than just refer to the function. Python goes back and looks up the definition, and only then, executes the code inside the function definition. The term for this action is a function call or function invocation. Note, in the function call there is no def, but there is the function name followed by parentheses.
function_name()
In many cases we will use a feature of program execution in Idle: that after program execution is completed, the Idle Shell still remembers functions defined in the program. This is not true if you run a program by selecting it directly in the operating system. The general assumption in this Tutorial will be that programs are run in Idle and the Idle Shell is the Shell referred to. It will be explicitly stated when you should run a program directly from the operating system. (With most of the examples in the tutorial, running from the operating system is OK – the execution method will not actually matter.)
Look at the example program birthday3.py. See it just adds two more lines, not indented. Can you guess what it does? Try it:
def happyBirthdayEmily(): #1
print "Happy Birthday to you!" #2
print "Happy Birthday to you!" #3
print "Happy Birthday, dear Emily." #4
print "Happy Birthday to you!" #5
happyBirthdayEmily() #6
happyBirthdayEmily() #7
The execution sequence is different from the textual sequence:
Functions alter execution order in several ways: statements not being executed as the definition is first read, and then when the function is called during execution, jumping to the function code, and back at the the end of the function execution.
If it also happens to be Andre's birthday, we might define a function happyBirthdayAndre, too. Think how to do that before going on ....
Here is example program birthday4.py where we add a function happyBirthdayAndre, and call them both. Guess what happens, and then try it:
def happyBirthdayEmily(): # same old function
print "Happy Birthday to you!"
print "Happy Birthday to you!"
print "Happy Birthday, dear Emily."
print "Happy Birthday to you!"
def happyBirthdayAndre():
print "Happy Birthday to you!"
print "Happy Birthday to you!"
print "Happy Birthday, dear Andre."
print "Happy Birthday to you!"
happyBirthdayEmily()
happyBirthdayAndre()
Again, everything is definitions except the last two lines. They are the only lines executed directly. The calls to the functions happen to be in the same order as their definitions, but that is arbitrary. If the last two lines were swapped, the order of operations would change. Do swap the last two lines so they appear as below, and see what happens when you execute the program:
happyBirthdayAndre()
happyBirthdayEmily()
Functions that you write can also call other functions you write. It is a good convention to have the main action of a program be in a function for easy reference. The example program birthday5.py has the two Happy Birthday calls inside a final function, main. Do you see that this version accomplishes the same thing as the last version? Run it.
def happyBirthdayEmily(): #1
print "Happy Birthday to you!" #2
print "Happy Birthday to you!" #3
print "Happy Birthday, dear Emily." #4
print "Happy Birthday to you!" #5
def happyBirthdayAndre(): #6
print "Happy Birthday to you!" #7
print "Happy Birthday to you!" #8
print "Happy Birthday, dear Andre." #9
print "Happy Birthday to you!" #10
def main(): #11
happyBirthdayAndre() #12
happyBirthdayEmily() #13
main() #14
If we want the program to do anything automatically when it is runs, we need one line outside of definitions! The final line is the only one directly executed, and it calls the code in main, which in turn calls the code in the other two functions.
Detailed order of execution:
There is one practical difference from the previous version. After execution, if we want to give another round of Happy Birthday to both persons, we only need to enter one further call in the Shell to:
main()
As a simple example emphasizing the significance of a line being indented, guess what the the example file order.py does, and run it to check:
def f():
print 'In function f'
print 'When does this print?'
f()
Modify the file so the second print statement is outdented like below. What should happen now? Try it:
def f():
print 'In function f'
print 'When does this print?'
f()
The lines indented inside the function definition are remembered first, and only executed when the function f is invoked at the end. The lines outside any function definition (not indented) are executed in order of appearance.
Exercise 1.11.3.1. * Write a program, poem.py, that defines a function that prints a short poem or song verse. Give a meaningful name to the function. Have the program end by calling the function three times, so the poem or verse is repeated three times.
As a young child, you probably heard Happy Birthday sung to a couple of people, and then you could sing to a new person, say Maria, without needing to hear the whole special version with Maria's name in it word for word. You had the power of abstraction. With examples like the versions for Emily and Andre, you could figure out what change to make it so the song could be sung to Maria!
Unfortunately, Python is not that smart. It needs explicit rules. If you needed to explain explicitly to someone how Happy Birthday worked in general, rather than just by example, you might say something like this:
First you have to be given a person's name. Then you sing the song with the person's name inserted at the end of the third line.
Python works something like that, but with its own syntax. The term “person's name” serves as a stand-in for the actual data that will be used, “Emily”, “Andre”, or “Maria”. This is just like the association with a variable name in Python. “person's name” is not a legal Python identifier, so we will use just person as this stand-in.
The function definition indicates that the variable name person will be used inside the function by inserting it between the parentheses of the definition. Then in the body of the definition of the function, person is used in place of the real data for any specific person's name. Read and then run example program birthday6.py:
def happyBirthday(person): #1
print "Happy Birthday to you!" #2
print "Happy Birthday to you!" #3
print "Happy Birthday, dear " + person + "." #4
print "Happy Birthday to you!" #5
happyBirthday('Emily') #6
happyBirthday('Andre') #7
In the definition heading for happyBirthday, person is referred to as a parameter, or a formal parameter. This variable name is a placeholder for the real name of the person being sung to.
The last two lines of the program, again, are the only ones outside of definitions, so they are the only ones executed directly. There is now an actual name between the parentheses in the function calls. The value between the parentheses here in the function call is referred to as an argument or actual parameter of the function call. The argument supplies the actual data to be used in the function execution. When the call is made, Python does this by associating the formal parameter name person with the actual parameter data, as in an assignment statement. In the first call, this actual data is 'Emily'. We say the actual parameter value is passed to the function.
The execution in greater detail:
The beauty of this system is that the same function definition can be used for a call with a different actual parameter variable, and then have a different effect. The value of the variable person is used in the third line of happyBirthday, to put in whatever actual parameter value was given.
This is the power of abstraction. It is one application of the most important principal in programming. Rather than have a number of separately coded parts with only slight variations, see where it is appropriate to combine them using a function whose parameters refer to the parts that are different in different situations while the code is written to be simultaneously appropriate for the separate specific situations, with the substitutions of the right parameter values.
You can go back to having a main function again, and everything works. Run birthday7.py:
def happyBirthday(person):
print "Happy Birthday to you!"
print "Happy Birthday to you!"
print "Happy Birthday, dear " + person + "."
print "Happy Birthday to you!"
def main():
happyBirthday('Emily')
happyBirthday('Andre')
main()
Exercise 1.11.4.1. * Make your own further change to the file and save it as birthdayMany.py: Add a function call, so Maria gets a verse, in addition to Emily and Andre. Also print a blank line between verses. (You may either do this by adding a print line to the function definition, or by adding a print line between all calls to the function.)
We can combine function parameters with user input, and have the program be able to print Happy Birthday for anyone. Check out the main method and run birthday_who.py:
def happyBirthday(person):
print "Happy Birthday to you!"
print "Happy Birthday to you!"
print "Happy Birthday, dear " + person + "."
print "Happy Birthday to you!"
def main():
userName = raw_input("Enter the Birthday person's name: ")
happyBirthday(userName)
main()
This last version illustrates several important ideas:
A function can have more than one parameter in a parameter list separated by commas. Here the example program addition5.py uses a function to make it easy to display many sum problems. Read and follow the code, and then run:
def sumProblem(x, y):
print 'The sum of %s and %s is %s.' % (x, y, x+y)
def main():
sumProblem(2, 3)
sumProblem(1234567890123, 535790269358)
a, b = input("Enter two comma separated numbers: ")
sumProblem(a, b)
main()
The actual parameters in the function call are evaluated left to right, and then these values are associated with the
formal parameter names in the function definition, also left to right. For example the function call with
actual parameters, f(actual1, actual2, actual3), calling the function f with definition heading
def f(formal1, formal2, formal3):
acts approximately as if the first lines executed inside the called function were
formal1 = actual1
formal2 = actual2
formal3 = actual3
Functions provide extremely important functionality to programs, allowing task to be defined once and performed repeatedly with different data. It is essential to see the difference between the formal parameters used to describe what is done inside the function definition (like x and y in the definition of sumProblem) ant the actual parameters (like 2 and 3 or 1234567890123 and 535790269358) which substitute for the formal parameters when the function is actually executed. The main method above uses three different sets of actual parameters in the three calls to sumProblem.
Exercise 1.11.5.1. '* Modify the program above and save it as quotientProb.py. The new program should have a quotientProblem function, printing as in the Exercise 1.10.4.2. The main method should test the function on several sets of literal values, and also test the function with input from the user.
You probably have used mathematical functions in algebra class, but they all had calculated values associated with them. For instance if you defined f(x) = x2, then it follows that f(3) is 32 = 9, and f(3) + f(4) is 32 + 42 = 25. Function calls in expressions get replaced during evaluation by the value of the function.
The corresponding definition and examples in Python would be the following, also in the example program return1.py. Read and run:
def f(x):
return x*x
print f(3)
print f(3) + f(4)
The new Python syntax is the return statement, with the word return followed by an expression. Functions that return values can be used in expressions, just like in math class. When an expression with a function call is evaluated, temporarily the function call is effectively replaced by its returned value. Inside the Python function, the value to be returned is given by the expression in the return statement. After the function f finishes executing from inside
print f(3)
it is as if the statement temporarily became
print 9
and similarly when executing
print f(3) + f(4)
the interpreter first evaluates f(3) and effectively replaces the call by the returned result, 9, as if the statement temporarily became
print 9 + f(4)
and then the interpreter evaluates f(4) and effectively replaces the call by the returned result, 16, as if the statement temporarily became
print 9 + 16
resulting finally in 25 being calculated and printed.
Python functions can return any type of data, not just numbers, and there can be any number of statements executed before the return statement. Read, follow, and run the example program return2.py:
def lastFirst(firstName, lastName): #1
separator = ', ' #2
result = lastName + separator + firstName #3
return result #4
print lastFirst('Benjamin', 'Franklin') #5
print lastFirst('Andrew', 'Harrington') #6
The code above has a new feature, variables separator and result are given a value in the function, but separator and result are not among the formal parameters. The assignments work as you would expect here. More on this shortly, in Section 1.11.8 on local scope.
Details of the execution:
Compare return2.py and addition5.py, from the previous section. Both use functions. Both print, but where the printing is done differs. The function sumProblem prints directly inside the function and returns nothing explicitly. On the other hand lastFirst does not print anything but returns a string. The caller gets to decide what to do with the string, and above it is printed in the main program.
Open addition5.py again, and introduce a common mistake. Change the last line of the function main inserting print, so it says
print sumProblem(a, b)
Then try running the program. The desired printing is actually done inside the function sumProblem. You introduced a statement to print what sumProblem returns. Although sumProblem returns nothing explicitly, Python does make every function return something. If there is nothing explicitly returned, the special value None is returned. You should see that in the Shell output. This is a fairly common error. If you see a 'None' is your output where you do not expect it, it is likely that you have printed the return value of a function that did not return anything explicitly!
Exercise 1.11.6.1. Create quotientReturn.py by modifying quotientProb.py from Exercise 1.11.5.1 so that the program accomplishes the same thing, but everywhere change the quotientProblem function into one called quotientString that merely returns the string rather than printing the string directly. Have the main function print the result of each call to the quotientString function.
The remainder of Section1.11 covers finer points about functions that you might skip on a first reading.
We are only doing tiny examples so far to get the basic idea of functions. In much larger programs, functions are useful to manage complexity, splitting things up into logically related, modest sized pieces. Programmers are both writers of functions and consumers of the other functions called inside their functions. It is useful to keep those two roles separate:
The user of an already written function needs to know:
How this is accomplished is not relevant at this point. For instance, you use the work of the Python development team, calling functions that are built into the language. You need know the three facts about the functions you call. You do not need to know exactly how the function accomplishes its purpose.
On the other hand when you write a function you need to figure out exactly how to accomplish your goal, name relevant variables, and write your code, which brings us to the next section.
For the logic of writing functions, it is important that the writer of a function knows the names of variables inside the function. On the other hand, if you are only using a function, maybe written by someone unknown to you, you should not care what names are given to values used internally in the implementation of the function you are calling. Python enforces this idea with local scope rules: Variable names initialized and used inside one function are invisible to other functions. Such variables are called local variables. For example, an elaboration of the earlier program return2.py might have its lastFirst function with its local variable separator, but it might also have another function that defines a separator variable, maybe with a different value like '\n'. They do not conflict. They are independent. This avoids lots of errors!
For example, the following code in the example program badScope.py causes an execution error. Read it and run it, and see:
def main():
x = 3
f()
def f():
print x #f does not know about the x defined in main
main()
We will fix this error below. The execution error message mentions “global name”. Names defined outside any function definition, at the “top-level” of your program are called global. They are a special case. They are discussed more in the next section.
If you do want local data from one function to go to another, include parameters! Read and compare and try the program goodScope.py:
def main():
x = 3
f(x)
def f(x):
print x
main()
With parameter passing, the parameter name x in the function f does not need to match the name of the actual parameter in main. The definition of f could just as well have been:
def f(whatever):
print whatever
If you define global variables (outside of any function definition), they are visible inside all your functions. It is good programming practice to avoid defining global variables and instead to put your variables inside functions. One common exception is constants: A constant is a name that you give a fixed data value to, assigning a value to the name only in a single assignment statement, and then using the name of the fixed data value in expressions later. A simple example program is constant.py:
PI = 3.14159265358979 # global constant -- only place the value of PI is set
def circleArea(radius):
return PI*radius*radius # use value of global constant PI
def circleCircumference(radius):
return 2*PI*radius # use value of global constant PI
print 'circle area with radius 5:', circleArea(5)
print 'circumference with radius 5:', circleCircumference(5)
This example uses numbers with decimal points, discussed more in Section 1.14.1.
There are further issues with global variables. A discussion is postponed.
Function names defined at the top-level also have global scope. This is what allows you to use one function you defined inside another function you define.
In common usage, a dictionary is a collection of words matched with their definitions. Given a word, you can look up its definition. Python has a built in dictionary type called dict which you can use to create dictionaries with arbitrary definitions for character strings. It can be used for the common usage, as in a simple English-Spanish dictionary.
Look at the example program spanish1.py and run it.
"""A tiny English to Spanish dictionary is created,
using the Python dictionary type dict.
Then the dictionary is used, briefly.
"""
spanish = dict()
spanish['hello'] = 'hola'
spanish['yes'] = 'si'
spanish['one'] = 'uno'
spanish['two'] = 'dos'
spanish['three'] = 'tres'
spanish['red'] = 'rojo'
spanish['black'] = 'negro'
spanish['green'] = 'verde'
spanish['blue'] = 'azul'
print spanish['two']
print spanish['red']
First an empty dictionary is created using dict(), and it is assigned the descriptive name spanish.
To refer to the definition for a word, you use the dictionary name, follow it by the word inside square brackets. This notation can either be used on the left-hand side of an assignment to make (or remake) a definition, or it can be used in an expression (as in the print statements), where its definition is one stored earlier into the dictionary. For example,
spanish['hello'] = 'hola'
makes an entry in our spanish dictionary for 'hello' , where the definition matched to it is 'hola'.
print spanish['red']
retrieves the definition for 'red', which is 'rojo'.
Since the Spanish dictionary is defined at the top-level, the variable name spanish is still defined after the program runs: after running the program, use spanish in the Shell to check out the translations of some more words, other than 'two' and 'red'.
Creating the dictionary is quite a different activity from the use at the end of the code, so with functions to encapsulate the tasks, we could write the example program spanish2.py instead, with the same result:
"""A tiny English to Spanish dictionary is created,
using the Python dictionary type dict.
Then the dictionary is used, briefly.
"""
def createDictionary():
'''Returns a tiny Spanish dictionary'''
spanish = dict() # creates an empty dictionary
spanish['hello'] = 'hola'
spanish['yes'] = 'si'
spanish['one'] = 'uno'
spanish['two'] = 'dos'
spanish['three'] = 'tres'
spanish['red'] = 'rojo'
spanish['black'] = 'negro'
spanish['green'] = 'verde'
spanish['blue'] = 'azul'
return spanish
def main():
dictionary = createDictionary()
print dictionary['two']
print dictionary['red']
main()
This code illustrates several things about functions.
Python dictionaries are actually more general than the common use of dictionaries. They do not have to associate words and their string definitions. They can associate many types of objects with some arbitrary object. The more general Python terminology for word and definition are key and value. Given a key, you can look up the corresponding value. The only restriction on the key is that it be an immutable type. This means that a value of the key's type cannot be changed internally. Strings and numbers are immutable. A dictionary is mutable: its value can be changed internally. (You can add new definitions to it!) We will see more mutable and immutable types later and explore more of the internal workings of data types.
Exercise 1.12.1.1. * Write a tiny Python program numDict.py that makes a dictionary whose keys are the words 'one', 'two', 'three', and 'four', and whose corresponding values are the numerical equivalents, 1, 2, 3, and 4 (ints, not strings). Include code to test the resulting dictionary by referencing several of the definitions and printing the results.
Dictionaries that have keys of string type can be used in a special way with format strings. Rather than choosing substitutions by positional sequence in a tuple, lookups can be made using keys in the dictionary. We reuse the createDictionary function from Section1.12.1, and just change the print statements in the main function. Read and run spanish3.py:
"""Illustrate using a dictionary with a format string."""
def createDictionary(): # same old function
'''Returns a tiny spanish dictionary'''
spanish = dict() # creates an empty dictionary
spanish['hello'] = 'hola'
spanish['yes'] = 'si'
spanish['one'] = 'uno'
spanish['two'] = 'dos'
spanish['three'] = 'tres'
spanish['red'] = 'rojo'
spanish['black'] = 'negro'
spanish['green'] = 'verde'
spanish['blue'] = 'azul'
return spanish
def main():
dictionary = createDictionary()
print "Count in Spanish: %(one)s, %(two)s, %(three)s, ..." % dictionary
print "Spanish colors: %(red)s, %(blue)s, %(green)s, ..." % dictionary
main()
Within the format strings, where there is a % signaling a substitution, it must be immediately followed by a dictionary key name in parentheses and then the rest of the format specifier (which in all the examples here, is just s indicating a string value), so in this example the format is always %(key)s. Note that the key is not in quotes. After the format string comes another % character as usual for the format operation, but it must be followed be just a single dictionary, not a tuple.7
Choosing between the tuple and dictionary forms of formatting: For format strings with only a few substitutions, and where the format string is not likely to be edited and rearranged much, the tuple format is shorter and simpler. If you actually want to substitute from a dictionary anyway, the dictionary format is obvious. If you have a long format string that you might want to edit and rearrange, or repeat the use the same substituted value several times, the dictionary formulation is likely convenient , even if you have to create the dictionary just for use in the format string.
At this point we have discussed in some detail everything that went into the first sample program, madlib.py, of Section 1.2.3! This is certainly the most substantial program so far.
Look at madlib.py again, see how we have used most of the ideas so far. If you want more description, you might look at section 1.2.3 again (or for the first time): it should make much more sense now.
Exercise 1.12.2.1. To confirm your better understanding of madlib.py, load it in the editor, rename it as myMadlib.py, and modify it to have a less lame story, with more and different entries in the dictionary. Make sure addPick is called for each key in your format string. Test your version.
We will use madlib.py as a basis for more substantial modifications in structure in Section 2.3.3.
Modern computers can do millions or even billions of instructions a second. With the techniques discussed so far, it would be hard to get a program that would run by itself for more than a fraction of a second.8 Practically, we cannot write millions of instructions to keep the computer busy. To keep a computer doing useful work we need repetition, looping back over the same block of code again and again. There are two Python statement types to do that: the simpler for loops, which we take up shortly, and while loops, which we take up later, in Section 3.3. Two preliminaries: First, the value of already defined variables can be updated. This will be particularly important in loops. We start by following how variables can be updated in an even simpler situation. Second, for loops involve sequence types, so we will first look at a basic sequence type: list. This is a long section. Go carefully.
The programs so far have defined and used variables, but other than in early shell examples we have not changed the value of existing variables. For now consider a particularly simple example, just chosen as an illustration, in the example file updateVar.py:
x = 3 #1
y = x + 2 #2
y = 2*y #3
x = y - x #4
print x, y #5
Can you predict the result? Run the program and check. Particularly if you did not guess right, it is important to understand what happens, one step at a time. That means keeping track of what changes to variables are made by each statement. In the table below, statements are referred to by the numbers labeling the lines in the code above. We can track the state of each variable after each line in executed. A dash is shown where a variable is not defined. For instance after line 1 is executed, a value is given to x, but y is still undefined. Then y gets a value in line 2. The comment on the right summarizes what is happening. Since x has the value 3 when line 2 starts, x+2 is the same as 3+2. In line three we use the fact that the right side of an assignment statement uses the values of variables when the line starts executing (what is left after the previous line of the table executed), but the assignment to the variable y on the left causes a change to y, and hence the updated value of y, 10, is shown in the table. Line 4 then changes x, using the latest value of y (10, not the initial value 5!). The result from line 5 confirms the values of x and y.
| Line | x | y | comment |
| 1 | 3 | - | |
| 2 | 3 | 5 | 5=3+2, using the value of x from the previous line |
| 3 | 3 | 10 | 10=2*5 on the right, use the value of y from the previous line |
| 4 | 7 | 19 | 7=10-3 on the right, use the value of x and y from the previous line |
| 5 | 7 | 10 | print: 7 10 |
The order of execution will always be the order of the lines in the table. In this simple sequential code, that also follows the textual order of the program. Following each line of execution of a program in order, carefully, keeping track of the current values of variables, will be called playing computer. A table like the one above is an organized way to keep track.
Lists are ordered sequences of arbitrary data. Tuples, that were mentioned briefly in connection with string formatting, satisfy the same description. The difference is that lists are mutable: the length of the sequence can be changed and elements substituted, unlike tuples. We will delay the discussion of changes to lists until a further introduction to objects. Lists can be written explicitly. Read the following examples
['red', 'green', 'blue']
[1, 3, 5, 7, 9, 11]
['silly', 57, 'mixed', -23, 'example']
[] # the empty list
The basic format is square-bracket-enclosed, comma-separated lists of arbitrary data (not parenthesis-enclosed as in tuples).
There is a built-in function range, that can be used to automatically generate lists that are regular arithmetic sequences. Try the following in the Shell:
range(4)
range(10)
The general pattern is
range(sizeOfList)
As you can see, you get a list returned, starting from 0, and ending one before the parameter. We will see there are good reasons to start from 0 in Python. One important property of lists generated by range(n) is that the total number of elements is n. The list omits the number n itself, but includes 0 instead.
With more parameters, the range function can be used to generate a much wider variety of sequences. The elaborations are discussed in Section 2.4.12 and Section 3.3.2.
Try the following in the Shell. You get a sequence of continuation lines before the Shell responds. The second and third lines should be automatically indented by the Shell, and be sure to enter another empty line (just Enter) at the end to get the Shell to respond.
for count in [1, 2, 3]:
print count
print 'Yes' * count
This is a for loop. It has the heading starting with for, followed by a variable name (count in this case), the word in, some sequence, and a final colon. As with function definitions and other heading lines ending with a colon, the colon at the end of the line indicates that a consistently indented block of statements follows to complete the for loop.
for item in sequence:
indented statements to repeat
The block of lines is repeated once for each element of the sequence, so in this example the two lines in the indented block are repeated three times. Furthermore the variable in the heading (count here) may be used in the block, and each time through it takes on the next value in the sequence, so the first time through the loop i is 1, then 2, and finally 3. Look again at the output and see that it matches this sequence.
There is a reason the interpreter waited to respond until after you entered an empty line: The interpreter did not know how long the loop block was going to be! The empty line is a signal to the interpreter that you are done with the loop block.
Look at the following example program for123.py, and run it.
for count in [1, 2, 3]: #1
print count #2
print 'Yes'*count #3
print 'Done counting.' #4
for color in ['red', 'blue', 'green']: #5
print color #6
In a file, where the interpreter does not need to respond immediately, the blank line is not necessary. Instead, as with a function definition or any other format with an indented block, you indicate being past the indented block by dedenting to line up with the for-loop heading. Hence in the code above, “Done Counting.” is printed once after the first loop completes all its repetitions. Execution ends with another simple loop.
As with the indented block in a function, it is important to get the indentation right. Alter the code above, so line 4 is indented:
for count in [1, 2, 3]: #1
print count #2
print 'Yes'*count #3
print 'Done counting.' #4
for color in ['red', 'blue', 'green']: #5
print color #6
Predict the change, and run the code again to test.
Loops are one of the most important features in programming. While the syntax is pretty simple, using them creatively to solve problems (rather than just look at a demonstration) is among the biggest challenges for many learners at an introductory level. One way to simplify the learning curve is to classify common situations and patterns. One of the simplest patterns is illustrated above, simple for-each loops.
for item in sequence
do some thing with item
(It would be even more like English if for were replace by for each, but the shorter version is the one used by Python.)
In the for-loop examples above, something is printed that is related to each item in the list. Printing is certainly one form of “do something”, but the possibilities for “do something” are completely general.
We can use a for-each loop to revise our first example. Recall the code from madlib.py:
addPick('animal', userPicks)
addPick('food', userPicks)
addPick('city', userPicks)
Each line is doing exactly the same thing, except varying the string used as the cue, while repeating the rest of the line. This is the for-each pattern, but we need to list the sequence that the cues come from. Read the alternative:
for cue in ['animal', 'food', 'city']: # heading
addPick(cue, userPicks) # body
If you wish to see or run the whole program with this small modification, see the example madlibloop.py.
It is important to understand the sequence of operations, how execution goes back and forth between the heading and the body. Here are the details:
This looping construction would be even handier if you were to modify the original mad lib example, and had a story with many more cues. Also this revision will allow for further improvements in Section 2.3.3, after we introduce more about string manipulation.
The examples above all used the value of the variable in the for-loop heading. An even simpler for-loop usage is when you just want to repeat the exact same thing a specific number of times. In that case only the length of the list, not the individual elements are important. We have already seen that the range function provides an ease way to produce a list with a specified number of elements. Read and run the example program repeat1.py:
for i in range(10):
print 'Hello'
In this situation, the variable i is not used inside the body of the for-loop.
The user could choose the number of times to repeat. Read and run the example program repeat2.py:
n = input('Enter the number of times to repeat: ')
for i in range(n):
print 'This is repetitious!'
Suppose I have a list of items called items, and I want to print out each item and number them successively. For instance if items is ['red', 'orange', 'yellow', 'green'], I would like to see the output:
1 red
2 orange
3 yellow
4 green
Read about the following thought process for developing this:
If I allow myself to omit the numbers, it is easy: For any item in the list, I can process it with
print item
and I just go through the list and do it for each one. (Copy and run if you like.)
items = ['red', 'orange', 'yellow', 'green']
for item in items:
print item
Clearly the more elaborate version with numbers has a pattern with some consistency, each line is at least in the form:
number item
but the number changes each time, and the numbers do not come straight from the list of items.
A variable can change, so it makes sense to have a variable number, so we have the potential to make it change correctly. We could easily get it right the first time, and then repeat the same number. Read and run the example program numberEntries1.py:
items = ['red', 'orange', 'yellow', 'green']
number = 1
for item in items:
print number, item
Of course this is still not completely correct, since the idea was to count. after the first time number is printed, it needs to be changed to 2 to be right the next time through the loop. This will make 2 appear correctly in the second output line: Read and run the example program numberEntries2.py:
items = ['red', 'orange', 'yellow', 'green']
number = 1
for item in items:
print number, item
number = 2
This is closer, but still not completely correct, since we never get to 3!We need a way to change the value of number that will work each time through the loop. The pattern of counting is simple, so simple in fact that you probably do not think consciously about how you go from one number to the next: You can describe the pattern by saying each successive number is one more than the previous number. We need to be able to change number so it is one more than it was before. That is the additional idea we need! Change the last line of the loop bodyto get the example program numberEntries3.py. See the addition and run it:
items = ['red', 'orange', 'yellow', 'green'] #1
number = 1 #2
for item in items: #3
print number, item #4
number = number + 1 #5
It is important to understand the step-by-step changes during execution. Below is another table showing the results of playing computer. The line numbers are much more important here to keep track of the flow of control, because of the jumping around at the end of the loop.
| Line | items | item | number | comment |
| 1 | ['red', 'orange', 'yellow', 'green'] | - | - | |
| 2 | ['red', 'orange', 'yellow', 'green'] | - | 1 | |
| 3 | ['red', 'orange', 'yellow', 'green'] | 'red' | 1 | start with item as first in sequence |
| 4 | ['red', 'orange', 'yellow', 'green'] | 'red' | 1 | print: 1 red |
| 5 | ['red', 'orange', 'yellow', 'green'] | 'red' | 2 | 2 = 1+1 |
| 3 | ['red', 'orange', 'yellow', 'green'] | 'orange' | 2 | on to the next element in sequence |
| 4 | ['red', 'orange', 'yellow', 'green'] | 'orange' | 2 | print 2 orange |
| 5 | ['red', 'orange', 'yellow', 'green'] | 'orange' | 3 | 3=2+1 |
| 3 | ['red', 'orange', 'yellow', 'green'] | 'yellow' | 3 | on to the next element in sequence |
| 4 | ['red', 'orange', 'yellow', 'green'] | 'yellow' | 3 | print 3 yellow |
| 5 | ['red', 'orange', 'yellow', 'green'] | 'yellow' | 4 | 4=3+1 |
| 3 | ['red', 'orange', 'yellow', 'green'] | 'green' | 4 | on to the last element in sequence |
| 4 | ['red', 'orange', 'yellow', 'green'] | 'green' | 4 | print 4 green |
| 5 | ['red', 'orange', 'yellow', 'green'] | 'green' | 5 | 5=4+1 |
| 3 | ['red', 'orange', 'yellow', 'green'] | 'green' | 5 | sequence done, end loop and code |
The final value of number is never used, but that is OK. What we want is printed.
This short example illustrates a lot of ideas:
There is a general pattern to loops with successive modification of a variable like number above:
This information can be put in a code outline:
Initialize variables to be modified
Loop heading controlling the repetition
Do the desired action with the current variables
Modify variables to be ready for the action the next time
If you compare this pattern to the for-each and simple repeat loops in Section 1.13.4, you see that the examples there were simpler. There was no explicit variable modification needed to prepare for the next time though the loop. We will refer to the latest, more general pattern as a successive modification loop.
Functions are handy for encapsulating an idea for use and reuse in a program, and also for testing. We can write a function to number a list, and easily test it with different data. Read and run the example program numberEntries4.py:
def numberList(items):
'''Print each item in a list items, numbered in order.'''
number = 1
for item in items:
print number, item
number = number + 1
def main():
numberList(['red', 'orange', 'yellow', 'green'])
print
numberList(['apples', 'pears', 'bananas'])
main()
Make sure you follow the whole sequence! This program has the most complicated flow of control so far, changing both for function calls and loops.
Suppose you want to add up all the numbers in a list, nums. Let us plan this as a function from the beginning, so read the code below. We can start with:
def sumList(nums):
'''Return the sum of the numbers in nums.'''
If you do not see what to do right away, a useful thing to do is write down a concrete case, and think how you would solve it, in complete detail. If nums is ['2', '6' ,'3', '8'], you would likely calculate
2+6 is 8
8 + 3 is 11
11 + 8 is 19
19 is the answer to be returned.
Since the list may be arbitrarily long, you need a loop. Hence you must find a pattern so that you can keep reusing the same statements in the loop. Obviously you are using each number in the sequence in order. You also generate a sum in each step, which you reuse in the next step. The pattern is different, however, in the first line, 2+6 is 8: there is no previous sum, and you use two elements from the list. The 2 is not added to a previous sum.
Although it is not the shortest way to do the calculation by hand, 2 is a sum of 0 + 2: We can make the pattern consistent and calculate:
start with a sum of 0
0 + 2 is 2
2 + 6 is 8
8 + 3 is 11
11 + 8 is 19
19 is the answer.
Then the second part of each sum is a number from the list, nums. If we call the number from the list num, the main calculation line in the loop could be
nextSum = sum + num
The trick is to use the same line of code the next time through the loop. That means what was nextSum in one pass becomes the sum in the next pass. One way to handle that is:
sum = 0
for num in nums:
nextSum = sum + num
sum = nextSum
Do you see the pattern? Again it is
initialization
loop heading
main work to be repeated
preparation for the next time through the loop
Sometimes the two general loop steps can be combined. This is such a case. Since nextSum is only used once, we can just substitute its value where it is used and simplify to:
sum = 0
for num in nums:
sum = sum + num
so the whole function, with the return statement is:
def sumList(nums): #1
'''Return the sum of the numbers in nums.'''
sum = 0 #2
for num in nums: #3
sum = sum + num #4
return sum #5
With the following (not indented) line below used to test the function, you have the example program sumNums.py. Run it.
print sumList([5, 2, 4, 7])
The pattern used here is certainly successive modification (of the sum variable). It is useful to giver a more specialized name for this version of the pattern here. It follows an accumulation pattern:
initialize the accumulation to include none of the sequence (sum = 0 here)
for item in sequence :
new value of accumulation = result of combining item with last value of accumulation
This pattern will work in many other situations besides adding numbers.
Exercise 1.13.7.1. * Suppose the function sumList, is called with the parameter [5, 2, 4, 7]. Play computer on this call. Make sure there is a row in the table for each line executed in the program, each time it is executed. In each row enter which program line is being executed and show all changes caused to variables by the execution of the line. A table is started for you below. The final line of your table should be for line 5, with the comment, “return 18”. If you do something like this longhand, and the same long value repeats a number of times, it is more convenient to put a ditto (“) for each repeated variable value or even leave it blank. If you want to do it on a computer you can start from the first table in example file playComputerSumStub.rtf. First save the file as playComputerSum.rtf.
| Line | nums | sum | num | comment |
| 1 | [5, 2, 4, 7'] | - | - | |
| 2 | ||||
Exercise 1.13.7.2. * Write a program testSumList.py which includes a main function to test the sumList function several times. Include a test for the extreme case, with an empty list.
Exercise 1.13.7.3. ** Complete the following function. This starting code is in joinAllStub.py. Save it to the new name joinAll.py. Note the way an example is given in the documentation string. It simulates the use of the function in the Shell. This is a common convention:
def joinStrings(stringList):
'''Join all the strings in stringList into one string,
and return the result. For example:
>>> print joinStrings(['very', 'hot', 'day'])
'veryhotday'
'''
Testing code by running it is fine, but looking at the results does not mean you really understand what is going on, particularly if there is an error! People who do not understand what is happening are likely to make random changes to their code in an attempt to fix errors. This is a very bad, increasingly self-defeating practice, since you are likely to never learn where the real problem lies, and the same problem is likely to come back to bite you.
It is important to be able to predict accurately what code will do. We have illustrated playing computer on a variety of small chunks of code.
Playing computer can help you find bugs (errors in your code). Some errors are syntax errors caught by the interpreter in translation. Some errors are only caught by the interpreter during execution, like failing to have a value for a variable you use. Other errors are not caught by the interpreter at all – you just get the wrong answer. These are called logical errors. Earlier logical errors can also trigger an execution error later. This is when playing computer is particularly useful.
A common error in trying to write the numberList function would be to have:
def numberList(items): # WRONG code for illustration!!!! #1
'''Print each item in a list items, numbered in order.''' #2
for item in items: #3
number = 1 #4
print number, item #5
number = number + 1 #6
You can run this code in numberEntriesWRONG.py and see that it produces the wrong answer. If you play computer on the call to numberList(['apples', 'pears', 'bananas']), you can see the problem:
| Line | items | item | number | comment |
| 1 | ['apples', 'pears', 'bananas'] | - | - | pass actual parameter value to items |
| 3 | ['apples', 'pears', 'bananas'] | 'apples' | - | start with item as first in sequence |
| 4 | ['apples', 'pears', 'bananas'] | 'apples' | 1 | |
| 5 | ['apples', 'pears', 'bananas'] | 'apples' | 1 | print: 1 apples |
| 6 | ['apples', 'pears', 'bananas'] | 'apples' | 2 | 2 = 1+1 |
| 3 | ['apples', 'pears', 'bananas'] | 'pears' | 2 | on to the next element in sequence |
| 4 | ['apples', 'pears', 'bananas'] | 'apples' | 1 | |
| 5 | ['apples', 'pears', 'bananas'] | 'pears' | 1 | print: 1 pears OOPS! |
If you go step by step you should see where the incorrect 1 came from: the initialization is repeated each time in the loop at line 4, undoing the incrementing of number in line 6, messing up your count. Always be careful that your one-time initialization for a loop goes before the loop, not in it!
Functions can also return values. Consider the Python for this mathematical sequence: define the function m(x) = 5x, let y = 3; find m(y) + m(2y-1).
def m(x): #1
return 5*x #2
y = 3 #3
print m(y) + m(2*y-1) #4
A similar example was considered in Section 1.11.6, but now add the idea of playing computer and recording the sequence in a table. Like when you simplify a mathematical expression, Python must complete the innermost parts first. Tracking the changes means following the function calls carefully and using the values returned. Again a dash '-' is used in the table to indicate an undefined variable. Not only are local variables like formal parameters undefined before they are first used, they are also undefined after the termination of the function,
| Line | x | y | comment |
| 3 | - | 3 | (definitions before this) |
| 4 | - | 3 | start on: print m(y) + m(2*y-1); find m(y), which is m(3) |
| 1 | 3 | 3 | pass 3 to function m, so x =3 |
| 2 | 3 | 3 | return 5*3 = 15 |
| 4 | - | 3 | substitute result: print 15 + m(2*y-1), find m(2*y-1), which is m(2*3-1) = m(5) |
| 1 | 5 | 3 | pass 5 to function m, so x=5 |
| 2 | 5 | 3 | return 5*5 = 25 |
| 4 | - |