Module 1 PDF Python 25 Scheme Syallabus Notes
Module 1 PDF Python 25 Scheme Syallabus Notes
The goal of this book is to teach you to think like a computer scientist. This way of thinking combines some of the
best features of mathematics, engineering, and natural science. Like mathematicians, computer scientists use formal
languages to denote ideas (specifically computations). Like engineers, they design things, assembling components into
systems and evaluating tradeoffs among alternatives. Like scientists, they observe the behavior of complex systems,
form hypotheses, and test predictions.
The single most important skill for a computer scientist is problem solving. Problem solving means the ability to
formulate problems, think creatively about solutions, and express a solution clearly and accurately. As it turns out, the
process of learning to program is an excellent opportunity to practice problem-solving skills. That’s why this chapter
is called, The way of the program.
On one level, you will be learning to program, a useful skill by itself. On another level, you will use programming as
a means to an end. As we go along, that end will become clearer.
The programming language you will be learning is Python. Python is an example of a high-level language; other
high-level languages you might have heard of are C++, PHP, Pascal, C#, and Java.
As you might infer from the name high-level language, there are also low-level languages, sometimes referred to as
machine languages or assembly languages. Loosely speaking, computers can only execute programs written in low-
level languages. Thus, programs written in a high-level language have to be translated into something more suitable
before they can run.
Almost all programs are written in high-level languages because of their advantages. It is much easier to program in a
high-level language so programs take less time to write, they are shorter and easier to read, and they are more likely
to be correct. Second, high-level languages are portable, meaning that they can run on different kinds of computers
with few or no modifications.
The engine that translates and runs Python is called the Python Interpreter: There are two ways to use it: immediate
mode and script mode. In immediate mode, you type Python expressions into the Python Interpreter window, and the
interpreter immediately shows the result:
3
How to Think Like a Computer Scientist: Learning with Python 3 Documentation, Release 3rd
Edition
The >>> is called the Python prompt. The interpreter uses the prompt to indicate that it is ready for instructions. We
typed 2 + 2, and the interpreter evaluated our expression, and replied 4, and on the next line it gave a new prompt,
indicating that it is ready for more input.
Alternatively, you can write a program in a file and use the interpreter to execute the contents of the file. Such a file is
called a script. Scripts have the advantage that they can be saved to disk, printed, and so on.
Working directly in the interpreter is convenient for testing short bits of code because you get immediate feedback.
Think of it as scratch paper used to help you work out problems. Anything longer than a few lines should be put into
a script.
When you are writing a script you need something like a text editor. With this we mean a program on your computer
that changes text files, not something that also does layout like a word processor such as Microsoft Word or LibreOffice
Writer. A few examples of text editors are Notepad, Notepad++, vim, emacs and sublime.
For Python (and many other programming languages) there are programs that include both a text editor and a way to in-
teract with the interpreter. We call these development environments (sometimes Integrated Development Environment
or IDE). For Python these can include (among many others) Spyder, Thonny or IDLE. There are also development
environments that run in your browser. One example of this is Jupyter Notebook.
The choice of development environment is quite personal, but if you are following a course based on this book the
teacher will probably recommend one. That recommendation is handy to follow if you need help using the environ-
ment.
The important thing to remember is that Python itself does not care in what editor you write your code. As long as
you write correct syntax (with the right tabs and spaces) Python can run your program. The editor is only there to help
you.
A program is a sequence of instructions that specifies how to perform a computation. The computation might be
something mathematical, such as solving a system of equations or finding the roots of a polynomial, but it can also
be a symbolic computation, such as searching and replacing text in a document or (strangely enough) compiling a
program.
The details look different in different languages, but a few basic instructions appear in just about every language:
input Get data from the keyboard, a file, or some other device such as a sensor.
output Display data on the screen or send data to a file or other device such as a motor.
math Perform basic mathematical operations like addition and multiplication.
conditional execution Check for certain conditions and execute the appropriate sequence of statements.
repetition Perform some action repeatedly, usually with some variation.
Believe it or not, that’s pretty much all there is to it. Every program you’ve ever used, no matter how complicated,
is made up of instructions that look more or less like these. Thus, we can describe programming as the process of
breaking a large, complex task into smaller and smaller subtasks until the subtasks are simple enough to be performed
with sequences of these basic instructions.
That may be a little vague, but we will come back to this topic later when we talk about algorithms.
Programming is a complex process, and because it is done by human beings, it often leads to errors. Programming
errors are called bugs and the process of tracking them down and correcting them is called debugging. Use of the
term bug to describe small engineering difficulties dates back to at least 1889, when Thomas Edison had a bug with
his phonograph.
Three kinds of errors can occur in a program: syntax errors, runtime errors, and semantic errors. It is useful to
distinguish between them in order to track them down more quickly.
Python can only execute a program if the program is syntactically correct; otherwise, the process fails and returns an
error message. Syntax refers to the structure of a program and the rules about that structure. For example, in English,
a sentence must begin with a capital letter and end with a period. this sentence contains a syntax error. So does this
one
For most readers, a few syntax errors are not a significant problem, which is why we can read the poetry of E. E.
Cummings without problems. Python is not so forgiving. If there is a single syntax error anywhere in your program,
Python will display an error message and quit, and you will not be able to run your program. During the first few
weeks of your programming career, you will probably spend a lot of time tracking down syntax errors. As you gain
experience, though, you will make fewer errors and find them faster.
The second type of error is a runtime error, so called because the error does not appear until you run the program. These
errors are also called exceptions because they usually indicate that something exceptional (and bad) has happened.
Runtime errors are rare in the simple programs you will see in the first few chapters, so it might be a while before you
encounter one.
The third type of error is the semantic error. If there is a semantic error in your program, it will run successfully, in
the sense that the computer will not generate any error messages, but it will not do the right thing. It will do something
else. Specifically, it will do what you told it to do.
The problem is that the program you wrote is not the program you wanted to write. The meaning of the program (its
semantics) is wrong. Identifying semantic errors can be tricky because it requires you to work backward by looking at
the output of the program and trying to figure out what it is doing.
One of the most important skills you will acquire is debugging. Although it can be frustrating, debugging is one of the
most intellectually rich, challenging, and interesting parts of programming.
In some ways, debugging is like detective work. You are confronted with clues, and you have to infer the processes
and events that led to the results you see.
Debugging is also like an experimental science. Once you have an idea what is going wrong, you modify your program
and try again. If your hypothesis was correct, then you can predict the result of the modification, and you take a step
closer to a working program. If your hypothesis was wrong, you have to come up with a new one. As Sherlock Holmes
pointed out, When you have eliminated the impossible, whatever remains, however improbable, must be the truth. (A.
Conan Doyle, The Sign of Four)
For some people, programming and debugging are the same thing. That is, programming is the process of gradually
debugging a program until it does what you want. The idea is that you should start with a program that does something
and make small modifications, debugging them as you go, so that you always have a working program.
For example, Linux is an operating system kernel that contains millions of lines of code, but it started out as a simple
program Linus Torvalds used to explore the Intel 80386 chip. According to Larry Greenfield, one of Linus’s earlier
projects was a program that would switch between displaying AAAA and BBBB. This later evolved to Linux (The
Linux Users’ Guide Beta Version 1).
Later chapters will make more suggestions about debugging and other programming practices.
Natural languages are the languages that people speak, such as English, Spanish, and French. They were not designed
by people (although people try to impose some order on them); they evolved naturally.
Formal languages are languages that are designed by people for specific applications. For example, the notation
that mathematicians use is a formal language that is particularly good at denoting relationships among numbers and
symbols. Chemists use a formal language to represent the chemical structure of molecules. And most importantly:
Programming languages are formal languages that have been designed to express computations.
Formal languages tend to have strict rules about syntax. For example, 3+3=6 is a syntactically correct mathematical
statement, but 3=+6$ is not. H2 O is a syntactically correct chemical name, but 2 Zz is not.
Syntax rules come in two flavors, pertaining to tokens and structure. Tokens are the basic elements of the language,
such as words, numbers, parentheses, commas, and so on. In Python, a statement like print("Happy New Year
for ",2013) has 6 tokens: a function name, an open parenthesis (round bracket), a string, a comma, a number, and
a close parenthesis.
It is possible to make errors in the way one constructs tokens. One of the problems with 3=+6$ is that $ is not a legal
token in mathematics (at least as far as we know). Similarly, 2 Zz is not a legal token in chemistry notation because
there is no element with the abbreviation Zz.
The second type of syntax rule pertains to the structure of a statement— that is, the way the tokens are arranged.
The statement 3=+6$ is structurally illegal because you can’t place a plus sign immediately after an equal sign.
Similarly, molecular formulas have to have subscripts after the element name, not before. And in our Python example,
if we omitted the comma, or if we changed the two parentheses around to say print)"Happy New Year for
",2013( our statement would still have six legal and valid tokens, but the structure is illegal.
When you read a sentence in English or a statement in a formal language, you have to figure out what the structure of
the sentence is (although in a natural language you do this subconsciously). This process is called parsing.
For example, when you hear the sentence, “The other shoe fell”, you understand that the other shoe is the subject and
fell is the verb. Once you have parsed a sentence, you can figure out what it means, or the semantics of the sentence.
Assuming that you know what a shoe is and what it means to fall, you will understand the general implication of this
sentence.
Although formal and natural languages have many features in common — tokens, structure, syntax, and semantics —
there are many differences:
ambiguity Natural languages are full of ambiguity, which people deal with by using contextual clues and other
information. Formal languages are designed to be nearly or completely unambiguous, which means that any
statement has exactly one meaning, regardless of context.
redundancy In order to make up for ambiguity and reduce misunderstandings, natural languages employ lots of
redundancy. As a result, they are often verbose. Formal languages are less redundant and more concise.
literalness Formal languages mean exactly what they say. On the other hand, natural languages are full of idiom and
metaphor. If someone says, “The other shoe fell”, there is probably no shoe and nothing falling. You’ll need to
find the original joke to understand the idiomatic meaning of the other shoe falling. Yahoo! Answers thinks it
knows!
People who grow up speaking a natural language—everyone—often have a hard time adjusting to formal languages.
In some ways, the difference between formal and natural language is like the difference between poetry and prose, but
more so:
poetry Words are used for their sounds as well as for their meaning, and the whole poem together creates an effect or
emotional response. Ambiguity is not only common but often deliberate.
prose The literal meaning of words is more important, and the structure contributes more meaning. Prose is more
amenable to analysis than poetry but still often ambiguous.
program The meaning of a computer program is unambiguous and literal, and can be understood entirely by analysis
of the tokens and structure.
Here are some suggestions for reading programs (and other formal languages). First, remember that formal languages
are much more dense than natural languages, so it takes longer to read them. Also, the structure is very important, so
it is usually not a good idea to read from top to bottom, left to right. Instead, learn to parse the program in your head,
identifying the tokens and interpreting the structure. Finally, the details matter. Little things like spelling errors and
bad punctuation, which you can get away with in natural languages, can make a big difference in a formal language.
Traditionally, the first program written in a new language is called Hello, World! because all it does is display the
words, Hello, World! In Python, the script looks like this: (For scripts, we’ll show line numbers to the left of the
Python statements.)
1 print("Hello, World!")
This is an example of using the print function, which doesn’t actually print anything on paper. It displays a value on
the screen. In this case, the result shown is
1 Hello, World!
The quotation marks in the program mark the beginning and end of the value; they don’t appear in the result.
Some people judge the quality of a programming language by the simplicity of the Hello, World! program. By this
standard, Python does about as well as possible.
A value is one of the fundamental things — like a letter or a number — that a program manipulates. The values we
have seen so far are 4 (the result when we added 2 + 2), and "Hello, World!".
These values are classified into different classes, or data types: 4 is an integer, and "Hello, World!" is a string,
so-called because it contains a string of letters. You (and the interpreter) can identify strings because they are enclosed
in quotation marks.
If you are not sure what class a value falls into, Python has a function called type which can tell you.
Not surprisingly, strings belong to the class str and integers belong to the class int. Less obviously, numbers with a
decimal point belong to a class called float, because these numbers are represented in a format called floating-point.
At this stage, you can treat the words class and type interchangeably. We’ll come back to a deeper understanding of
what a class is in later chapters.
>>> type(3.2)
<class 'float'>
What about values like "17" and "3.2"? They look like numbers, but they are in quotation marks like strings.
>>> type("17")
<class 'str'>
>>> type("3.2")
<class 'str'>
They’re strings!
Strings in Python can be enclosed in either single quotes (') or double quotes ("), or three of each (''' or """)
11
How to Think Like a Computer Scientist: Learning with Python 3 Documentation, Release 3rd
Edition
Double quoted strings can contain single quotes inside them, as in "Bruce's beard", and single quoted strings
can have double quotes inside them, as in 'The knights who say "Ni!"'.
Strings enclosed with three occurrences of either quote symbol are called triple quoted strings. They can contain either
single or double quotes:
Python doesn’t care whether you use single or double quotes or the three-of-a-kind quotes to surround your strings:
once it has parsed the text of your program or command, the way it stores the value is identical in all cases, and the
surrounding quotes are not part of the value. But when the interpreter wants to display a string, it has to decide which
quotes to use to make it look like a string.
So the Python language designers usually chose to surround their strings by single quotes. What do think would
happen if the string already contained single quotes?
When you type a large integer, you might be tempted to use commas between groups of three digits, as in 42,000.
The same goes for entering Dutch-style floating point numbers using a comma instead of a decimal dot. This is not a
legal integer in Python, but it does mean something else, which is legal:
>>> 42000
42000
>>> 42,000
(42, 0)
Well, that’s not what we expected at all! Because of the comma, Python chose to treat this as a pair of values. We’ll
come back to learn about pairs later. But, for the moment, remember not to put commas or spaces in your integers, no
matter how big they are. Also revisit what we said in the previous chapter: formal languages are strict, the notation is
concise, and even the smallest change might mean something quite different from what you intended.
2.2 Variables
One of the most powerful features of a programming language is the ability to manipulate variables. A variable is a
name that refers to a value.
The assignment statement gives a value to a variable:
This example makes three assignments. The first assigns the string value "What's up, Doc?" to a variable
named message. The second gives the integer 17 to n, and the third assigns the floating-point number 3.14159 to
a variable called pi.
The assignment token, =, should not be confused with equals, which uses the token ==. The assignment statement
binds a name, on the left-hand side of the operator, to a value, on the right-hand side. Basically, an assignment is an
order, and the equals operator can be read as a question mark. This is why you will get an error if you enter:
>>> 17 = n
File "<interactive input>", line 1
SyntaxError: can't assign to literal
Tip: When reading or writing code, say to yourself “n is assigned 17” or “n gets the value 17”. Don’t
say “n equals 17”.
A common way to represent variables on paper is to write the name with an arrow pointing to the variable’s value.
This kind of figure is called a state snapshot because it shows what state each of the variables is in at a particular
instant in time. (Think of it as the variable’s state of mind). Some editors and programming environments do this for
you, and allow you to click through the state of the program saving you some paper. This diagram shows the result of
executing the assignment statements:
If you ask the interpreter to evaluate a variable, it will produce the value that is currently linked to the variable:
>>> message
'What's up, Doc?'
>>> n
17
>>> pi
3.14159
We use variables in a program to “remember” things, perhaps the current score at the football game. But variables are
variable. This means they can change over time, just like the scoreboard at a football game. You can assign a value to
a variable, and later assign a different value to the same variable. (This is different from maths. In maths, if you give
‘x‘ the value 3, it cannot change to link to a different value half-way through your calculations!)
2.2. Variables 13
How to Think Like a Computer Scientist: Learning with Python 3 Documentation, Release 3rd
Edition
You’ll notice we changed the value of day three times, and on the third assignment we even made it refer to a value
that was of a different type.
A great deal of programming is about having the computer remember things, e.g. The number of missed calls on your
phone, and then arranging to update or change the variable when you miss another call.
Variable names can be arbitrarily long. They can contain both letters and digits, but they have to begin with a letter
or an underscore. Although it is legal to use uppercase letters, by convention we don’t. If you do, remember that case
matters. Bruce and bruce are different variables.
The underscore character ( _) can appear in a name. It is often used in names with multiple words, such as my_name
or price_of_tea_in_china.
There are some situations in which names beginning with an underscore have special meaning, so a safe rule for
beginners is to start all names with a letter.
If you give a variable an illegal name, you get a syntax error:
76trombones is illegal because it does not begin with a letter. more$ is illegal because it contains an illegal
character, the dollar sign. But what’s wrong with class?
It turns out that class is one of the Python keywords. Keywords define the language’s syntax rules and structure,
and they cannot be used as variable names.
Python has thirty-something keywords (and every now and again improvements to Python introduce or eliminate one
or two):
You might want to keep this list handy. If the interpreter complains about one of your variable names and you don’t
know why, see if it is on this list.
Programmers generally choose names for their variables that are meaningful to the human readers of the program —
they help the programmer document, or remember, what the variable is used for.
Caution: Beginners sometimes confuse “meaningful to the human readers” with “meaningful to the computer”.
So they’ll wrongly think that because they’ve called some variable average or pi, it will somehow magically
calculate an average, or magically know that the variable pi should have a value like 3.14159. No! The computer
doesn’t understand what you intend the variable to mean.
So you’ll find some instructors who deliberately don’t choose meaningful names when they teach beginners —
not because we don’t think it is a good habit, but because we’re trying to reinforce the message that you — the
programmer — must write the program code to calculate the average, and you must write an assignment statement
to give the variable pi the value you want it to have.
e = 3.1415
ray = 10
size = e * ray ** 2
pi = 3.1415
radius = 10
area = pi * radius ** 2
The above two snippets do exactly the same thing, but the bottom one uses the right kind of variable names. For the
computer there is no difference at all, but for a human, using the names and letters that are part of the conventional
way of writing things make all the difference in the world. Using e instead of pi completely confuses people,
while computers will just perform the calculation!
2.4 Statements
A statement is an instruction that the Python interpreter can execute. We have only seen the assignment statement so
far. Some other kinds of statements that we’ll see shortly are while statements, for statements, if statements, and
import statements. (There are other kinds too!)
When you type a statement on the command line, Python executes it. Statements don’t produce any result.
An expression is a combination of values, variables, operators, and calls to functions. If you type an expression at the
Python prompt, the interpreter evaluates it and displays the result:
>>> 1 + 1
2
>>> len("hello")
5
In this example len is a built-in Python function that returns the number of characters in a string. We’ve previously
seen the print and the type functions, so this is our third example of a function!
The evaluation of an expression produces a value, which is why expressions can appear on the right hand side of
assignment statements. A value all by itself is a simple expression, and so is a variable.
>>> 17
17
>>> y = 3.14
>>> x = len("hello")
>>> x
(continues on next page)
2.4. Statements 15
How to Think Like a Computer Scientist: Learning with Python 3 Documentation, Release 3rd
Edition
Operators are special tokens that represent computations like addition, multiplication and division. The values the
operator uses are called operands.
The following are all legal Python expressions whose meaning is more or less clear:
The tokens +, -, and *, and the use of parenthesis for grouping, mean in Python what they mean in mathematics. The
asterisk (*) is the token for multiplication, and ** is the token for exponentiation.
>>> 2 ** 3
8
>>> 3 ** 2
9
When a variable name appears in the place of an operand, it is replaced with its value before the operation is performed.
Addition, subtraction, multiplication, and exponentiation all do what you expect.
Example: so let us convert 645 minutes into hours:
Oops! In Python 3, the division operator / always yields a floating point result. What we might have wanted to know
was how many whole hours there are, and how many minutes remain. Python gives us two different flavors of the
division operator. The second, called floor division uses the token //. Its result is always a whole number — and if it
has to adjust the number it always moves it to the left on the number line. So 6 // 4 yields 1, but -6 // 4 might surprise
you!
>>> 7 / 4
1.75
>>> 7 // 4
1
>>> minutes = 645
>>> hours = minutes // 60
>>> hours
10
Take care that you choose the correct flavor of the division operator. If you’re working with expressions where you
need floating point values, use the division operator that does the division accurately.
Here we’ll look at three more Python functions, int, float and str, which will (attempt to) convert their arguments
into types int, float and str respectively. We call these type converter functions.
The int function can take a floating point number or a string, and turn it into an int. For floating point numbers, it
discards the decimal portion of the number — a process we call truncation towards zero on the number line. Let us
see this in action:
>>> int(3.14)
3
>>> int(3.9999) # This doesn't round to the closest int!
3
>>> int(3.0)
3
>>> int(-3.999) # Note that the result is closer to zero
-3
>>> int(minutes / 60)
10
>>> int("2345") # Parse a string to produce an int
2345
>>> int(17) # It even works if arg is already an int
17
>>> int("23 bottles")
The type converter float can turn an integer, a float, or a syntactically legal string into a float:
>>> float(17)
17.0
>>> float("123.45")
123.45
>>> str(17)
'17'
>>> str(123.45)
'123.45'
When more than one operator appears in an expression, the order of evaluation depends on the rules of precedence.
Python follows the same precedence rules for its mathematical operators that mathematics does. The acronym PEM-
DAS is a useful way to remember the order of operations:
1. Parentheses have the highest precedence and can be used to force an expression to evaluate in the order you
want. Since expressions in parentheses are evaluated first, 2 * (3-1) is 4, and (1+1)**(5-2) is 8. You
can also use parentheses to make an expression easier to read, as in (minute * 100) / 60, even though it
doesn’t change the result.
2. Exponentiation has the next highest precedence, so 2**1+1 is 3 and not 4, and 3*1**3 is 3 and not 27.
3. Multiplication and both Division operators have the same precedence, which is higher than Addition and
Subtraction, which also have the same precedence. So 2*3-1 yields 5 rather than 4, and 5-2*2 is 1, not
6.
4. Operators with the same precedence are evaluated from left-to-right. In algebra we say they are left-associative.
So in the expression 6-3+2, the subtraction happens first, yielding 3. We then add 2 to get the result 5. If
the operations had been evaluated from right to left, the result would have been 6-(3+2), which is 1. (The
acronym PEDMAS could mislead you to thinking that division has higher precedence than multiplication, and
addition is done ahead of subtraction - don’t be misled. Subtraction and addition are at the same precedence,
and the left-to-right rule applies.)
Due to some historical quirk, an exception to the left-to-right left-associative rule is the exponentiation operator
**, so a useful hint is to always use parentheses to force exactly the order you want when exponentiation is
involved:
The immediate mode command prompt of Python is great for exploring and experimenting with expressions like this.
In general, you cannot perform mathematical operations on strings, even if the strings look like numbers. The following
are illegal (assuming that message has type string):
Interestingly, the + operator does work with strings, but for strings, the + operator represents concatenation, not
addition. Concatenation means joining the two operands by linking them end-to-end. For example:
1 fruit = "banana"
2 baked_good = " nut bread"
3 print(fruit + baked_good)
The output of this program is banana nut bread. The space before the word nut is part of the string, and is
necessary to produce the space between the concatenated strings.
The * operator also works on strings; it performs repetition. For example, 'Fun'*3 is 'FunFunFun'. One of the
operands has to be a string; the other has to be an integer.
On one hand, this interpretation of + and * makes sense by analogy with addition and multiplication. Just as 4*3 is
equivalent to 4+4+4, we expect "Fun"*3 to be the same as "Fun"+"Fun"+"Fun", and it is. On the other hand,
there is a significant way in which string concatenation and repetition are different from integer addition and multipli-
cation. Can you think of a property that addition and multiplication have that string concatenation and repetition do
not?
2.10 Input
There is a built-in function in Python for getting input from the user:
The user of the program can enter the name and click OK, and when this happens the text that has been entered is
returned from the input function, and in this case assigned to the variable name.
Even if you asked the user to enter their age, you would get back a string like "17". It would be your job, as the
programmer, to convert that string into a int or a float, using the int or float converter functions we saw earlier.
2.11 Composition
So far, we have looked at the elements of a program — variables, expressions, statements, and function calls — in
isolation, without talking about how to combine them.
One of the most useful features of programming languages is their ability to take small building blocks and compose
them into larger chunks.
For example, we know how to get the user to enter some input, we know how to convert the string we get into a float,
we know how to write a complex expression, and we know how to print values. Let’s put these together in a small
four-step program that asks the user to input a value for the radius of a circle, and then computes the area of the circle
from the formula
Area = 𝜋𝑅2
Now let’s compose the first two lines into a single line of code, and compose the second two lines into another line of
code.
Such compact code may not be most understandable for humans, but it does illustrate how we can compose bigger
chunks from our building blocks.
If you’re ever in doubt about whether to compose code or fragment it into smaller steps, try to make it as simple as
you can for the human to follow. My choice would be the first case above, with four separate steps.
2.10. Input 19
How to Think Like a Computer Scientist: Learning with Python 3 Documentation, Release 3rd
Edition
The modulus operator works on integers (and integer expressions) and gives the remainder when the first number
is divided by the second. In Python, the modulus operator is a percent sign (%). The syntax is the same as for other
operators. It has the same precedence as the multiplication operator.
2.13 Glossary
assignment statement A statement that assigns a value to a name (variable). To the left of the assignment operator,
=, is a name. To the right of the assignment token is an expression which is evaluated by the Python interpreter
and then assigned to the name. The difference between the left and right hand sides of the assignment statement
is often confusing to new programmers. In the following assignment:
number = number + 1
number plays a very different role on each side of the =. On the right it is a value and makes up part of the
expression which will be evaluated by the Python interpreter before assigning it to the name on the left.
assignment token = is Python’s assignment token. Do not confuse it with equals, which is an operator for comparing
values.
composition The ability to combine simple expressions and statements into compound statements and expressions in
order to represent complex computations concisely.
concatenate To join two strings end-to-end.
data type A set of values. The type of a value determines how it can be used in expressions. So far, the types you
have seen are integers (int), floating-point numbers (float), and strings (str).
evaluate To simplify an expression by performing the operations in order to yield a single value.
expression A combination of variables, operators, and values that represents a single result value.
float A Python data type which stores floating-point numbers. Floating-point numbers are stored internally in two
parts: a base and an exponent. When printed in the standard format, they look like decimal numbers. Beware of
rounding errors when you use floats, and remember that they are only approximate values.
floor division An operator (denoted by the token //) that divides one number by another and yields an integer, or, if
the result is not already an integer, it yields the next smallest integer.
int A Python data type that holds positive and negative whole numbers.
keyword A reserved word that is used by the compiler to parse program; you cannot use keywords like if, def, and
while as variable names.
modulus operator An operator, denoted with a percent sign ( %), that works on integers and yields the remainder
when one number is divided by another.
operand One of the values on which an operator operates.
operator A special symbol that represents a simple computation like addition, multiplication, or string concatenation.
rules of precedence The set of rules governing the order in which expressions involving multiple operators and
operands are evaluated.
state snapshot A graphical representation of a set of variables and the values to which they refer, taken at a particular
instant during the program’s execution.
statement An instruction that the Python interpreter can execute. So far we have only seen the assignment statement,
but we will soon meet the import statement and the for statement.
str A Python data type that holds a string of characters.
value A number or string (or other things to be named later) that can be stored in a variable or computed in an
expression.
variable A name that refers to a value.
variable name A name given to a variable. Variable names in Python consist of a sequence of letters (a..z, A..Z, and
_) and digits (0..9) that begins with a letter. In best programming practice, variable names should be chosen so
that they describe their use in the program, making the program self documenting.
2.14 Exercises
1. Take the sentence: All work and no play makes Jack a dull boy. Store each word in a separate variable, then
print out the sentence on one line using print.
2. Add parenthesis to the expression 6 * 1 - 2 to change its value from 4 to -6.
3. Place a comment before a line of code that previously worked, and record what happens when you rerun the
program.
4. Start the Python interpreter and enter bruce + 4 at the prompt. This will give you an error:
2.14. Exercises 21
CHAPTER 3
Program Flow
There are many modules in Python that provide very powerful features that we can use in our own programs. Some of
these can send email, or fetch web pages. The one we’ll look at in this chapter allows us to create turtles and get them
to draw shapes and patterns.
The turtles are fun, but the real purpose of the chapter is to teach ourselves a little more Python, and to develop
our theme of computational thinking, or thinking like a computer scientist. Most of the Python covered here will be
explored in more depth later.
Let’s write a couple of lines of Python program to create a new turtle and start drawing a rectangle. (We’ll call the
variable that refers to our first turtle alex, but we can choose another name if we follow the naming rules from the
previous chapter).
23
How to Think Like a Computer Scientist: Learning with Python 3 Documentation, Release 3rd
Edition
Here are a couple of things we’ll need to understand about this program.
The first line tells Python to load a module named turtle. That module brings us two new types that we can
use: the Turtle type, and the Screen type. The dot notation turtle.Turtle means “The Turtle type that is
defined within the turtle module”. (Remember that Python is case sensitive, so the module name, with a lowercase t,
is different from the type Turtle.)
We then create and open what it calls a screen (we would prefer to call it a window), which we assign to variable
window. Every window contains a canvas, which is the area inside the window on which we can draw.
In line 3 we create a turtle. The variable alex is made to refer to this turtle.
So these first three lines have set things up, we’re ready to get our turtle to draw on our canvas.
In lines 5-7, we instruct the object alex to move, and to turn. We do this by invoking, or activating, alex’s methods
— these are the instructions that all turtles know how to respond to.
The last line plays a part too: the window variable refers to the window shown above. When we invoke its mainloop
method, it enters a state where it waits for events (like keypresses, or mouse movement and clicks). The program will
terminate when the user closes the window.
An object can have various methods — things it can do — and it can also have attributes — (sometimes called
properties). For example, each turtle has a color attribute. The method invocation alex.color("red") will make
alex red, and drawing will be red too. (Note the word color is spelled the American way!)
The color of the turtle, the width of its pen, the position of the turtle within the window, which way it is facing, and so
on are all part of its current state. Similarly, the window object has a background color, and some text in the title bar,
and a size and position on the screen. These are all part of the state of the window object.
Quite a number of methods exist that allow us to modify the turtle and the window objects. We’ll just show a couple.
In this program we’ve only commented those lines that are different from the previous example (and we’ve used a
different variable name for this turtle):
1 import turtle
2 window = turtle.Screen()
3 window.bgcolor("lightgreen") # Set the window background color
4 window.title("Hello, Tess!") # Set the window title
5
6 tess = turtle.Turtle()
7 tess.color("blue") # Tell tess to change her color
8 tess.pensize(3) # Tell tess to set her pen width
9
10 tess.forward(50)
11 tess.left(120)
(continues on next page)
14 window.mainloop()
When we run this program, this new window pops up, and will remain on the screen until we close it.
Just like we can have many different integers in a program, we can have many turtles. Each of them is called an
instance. Each instance has its own attributes and methods — so alex might draw with a thin black pen and be at
some position, while tess might be going in her own direction with a fat pink pen.
1 import turtle
2 window = turtle.Screen() # Set up the window and its attributes
3 window.bgcolor("lightgreen")
4 window.title("Tess & Alex")
5
31 window.mainloop()
Here is what happens when alex completes his rectangle, and tess completes her triangle:
• One of the key uses for comments is to record our mental chunking, and big ideas. They’re not always explicit
in the code.
• And, uh-huh, two turtles may not be enough for a herd. But the important idea is that the turtle module gives us
a kind of factory that lets us create as many turtles as we need. Each instance has its own state and behaviour.
When we drew the square, it was quite tedious. We had to explicitly repeat the steps of moving and turning four times.
If we were drawing a hexagon, or an octogon, or a polygon with 42 sides, it would have been worse.
So a basic building block of all programs is to be able to repeat some code, over and over again.
Python’s for loop solves this for us. Let’s say we have some friends, and we’d like to send them each an email inviting
them to our party. We don’t quite know how to send email yet, so for the moment we’ll just print a message for each
friend:
• The variable friend in the for statement at line 1 is called the loop variable. We could have chosen any
other variable name instead, such as broccoli: the computer doesn’t care.
• Lines 2 and 3 are the loop body. The loop body is always indented. The indentation determines exactly what
statements are “in the body of the loop”.
• On each iteration or pass of the loop, first a check is done to see if there are still more items to be processed.
If there are none left (this is called the terminating condition of the loop), the loop has finished. Program
execution continues at the next statement after the loop body, (e.g. in this case the next statement below the
comment in line 4).
• If there are items still to be processed, the loop variable is updated to refer to the next item in the list. This
means, in this case, that the loop body is executed here 7 times, and each time friend will refer to a different
friend.
• At the end of each execution of the body of the loop, Python returns to the for statement, to see if there are
more items to be handled, and to assign the next one to friend.
As a program executes, the interpreter always keeps track of which statement is about to be executed. We call this the
control flow, of the flow of execution of the program. When humans execute programs, they often use their finger to
point to each statement in turn. So we could think of control flow as “Python’s moving finger”.
Control flow until now has been strictly top to bottom, one statement at a time. The for loop changes this.
Control flow is often easy to visualize and understand if we draw a flowchart. This shows the exact steps and logic of
how the for statement executes.
To draw a square we’d like to do the same thing four times — move the turtle, and turn. We previously used 8 lines to
have alex draw the four sides of a square. This does exactly the same, but using just three lines:
1 for i in [0,1,2,3]:
2 alex.forward(50)
3 alex.left(90)
Some observations:
• While “saving some lines of code” might be convenient, it is not the big deal here. What is much more important
is that we’ve found a “repeating pattern” of statements, and reorganized our program to repeat the pattern. Find-
ing the chunks and somehow getting our programs arranged around those chunks is a vital skill in computational
thinking.
• The values [0,1,2,3] were provided to make the loop body execute 4 times. We could have used any four values,
but these are the conventional ones to use. In fact, they are so popular that Python gives us special built-in
range objects:
1 for i in range(4):
2 # Executes the body with i = 0, then 1, then 2, then 3
3 for x in range(10):
4 # Sets x to each of ... [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
• Since we do not need or use the variable i in this case, we could replace it with _, although this is not important
for the program flow, it is good style.
• Computer scientists like to count from 0!
• range can deliver a sequence of values to the loop variable in the for loop. They start at 0, and in these cases
do not include the 4 or the 10.
• Our little trick earlier to make sure that alex did the final turn to complete 360 degrees has paid off: if we had
not done that, then we would not have been able to use a loop for the fourth side of the square. It would have
become a “special case”, different from the other sides. When possible, we’d much prefer to make our code fit
a general pattern, rather than have to create a special case.
So to repeat something four times, a good Python programmer would do this:
1 for _ in range(4):
2 alex.forward(50)
3 alex.left(90)
By now you should be able to see how to change our previous program so that tess can also use a for loop to draw
her equilateral triangle.
But now, what would happen if we made this change?
A variable can also be assigned a value that is a list. So lists can also be used in more general situations, not only in
the for loop. The code above could be rewritten like this:
• Notice the difference between the method alex.color, which is “part of” the instance alex, and the variable
color, which is “part of” the main body of your program.
Turtle methods can use negative angles or distances. So tess.forward(-100) will move tess backwards, and
tess.left(-30) turns her to the right. Additionally, because there are 360 degrees in a circle, turning 30 to the
left will get tess facing in the same direction as turning 330 to the right! (The on-screen animation will differ, though
— you will be able to tell if tess is turning clockwise or counter-clockwise!)
This suggests that we don’t need both a left and a right turn method — we could be minimalists, and just have one
method. There is also a backward method. (If you are very nerdy, you might enjoy saying alex.backward(-100)
to move alex forward!)
Part of thinking like a scientist is to understand more of the structure and rich relationships in our field. So revising a
few basic facts about geometry and number lines, and spotting the relationships between left, right, backward, forward,
negative and positive distances or angles values is a good start if we’re going to play with turtles.
A turtle’s pen can be picked up or put down. This allows us to move a turtle to a different place without drawing a
line. The methods are
1 alex.penup()
2 alex.forward(100) # This moves alex, but no line is drawn
3 alex.pendown()
Every turtle can have its own shape. The ones available “out of the box” are arrow, blank, circle, classic,
square, triangle, turtle.
1 alex.shape("turtle")
We can speed up or slow down the turtle’s animation speed. (Animation controls how quickly the turtle turns and
moves forward). Speed settings can be set between 1 (slowest) to 10 (fastest). But if we set the speed to 0, it has a
special meaning — turn off animation and go as fast as possible.
1 alex.speed(10)
A turtle can “stamp” its footprint onto the canvas, and this will remain after the turtle has moved somewhere else.
Stamping works, even when the pen is up.
Let’s do an example that shows off some of these new features:
1 import turtle
2 window = turtle.Screen()
3 window.bgcolor("lightgreen")
4 tess = turtle.Turtle()
5 tess.shape("turtle")
6 tess.color("blue")
7
16 window.mainloop()
Be careful now! How many times was the body of the loop executed? How many turtle images do we see on the
screen? All except one of the shapes we see on the screen here are footprints created by stamp. But the program still
only has one turtle instance — can you figure out which one here is the real tess? (Hint: if you’re not sure, write a
new line of code after the for loop to change tess’ color, or to put her pen down and draw a line, or to change her
shape, etc.)
3.2 Conditionals
Programs get really interesting when we can test conditions and change the program behaviour depending on the
outcome of the tests. That’s what this part is about.
A Boolean value is either true or false. It is named after the British mathematician, George Boole, who first formulated
Boolean algebra — some rules for reasoning about and combining these values. This is the basis of all modern
computer logic.
In Python, the two Boolean values are True and False (the capitalization must be exactly as shown), and the Python
type is bool.
>>> type(True)
<class 'bool'>
>>> type(true)
Traceback (most recent call last):
File "<interactive input>", line 1, in <module>
NameError: name 'true' is not defined
A Boolean expression is an expression that evaluates to produce a result which is a Boolean value. For example, the
operator == tests if two values are equal. It produces (or yields) a Boolean value:
3.2. Conditionals 31
How to Think Like a Computer Scientist: Learning with Python 3 Documentation, Release 3rd
Edition
In the first statement, the two operands evaluate to equal values, so the expression evaluates to True; in the second
statement, 5 is not equal to 6, so we get False.
The == operator is one of six common comparison operators which all produce a bool result; here are all six:
Although these operations are probably familiar, the Python symbols are different from the mathematical symbols. A
common error is to use a single equal sign (=) instead of a double equal sign (==). Remember that = is an assignment
operator and == is a comparison operator. Also, there is no such thing as =< or =>.
Like any other types we’ve seen so far, Boolean values can be assigned to variables, printed, etc.
>>> age = 19
>>> old_enough_to_get_driving_licence = age >= 18
>>> print(old_enough_to_get_driving_licence)
True
>>> type(old_enough_to_get_driving_licence)
<class 'bool'>
There are three logical operators, and, or, and not, that allow us to build more complex Boolean expressions from
simpler Boolean expressions. The semantics (meaning) of these operators is similar to their meaning in English. For
example, x > 0 and x < 10 produces True only if x is greater than 0 and at the same time, x is less than 10.
n % 2 == 0 or n % 3 == 0 is True if either of the conditions is True, that is, if the number n is divisible
by 2 or it is divisible by 3. (What do you think happens if n is divisible by both 2 and by 3 at the same time? Will the
expression yield True or False? Try it in your Python interpreter.)
Finally, the not operator negates a Boolean value, so not (x > y) is True if (x > y) is False, that is, if x is
less than or equal to y. In other words: not True is False, and not False is True.
The expression on the left of the or operator is evaluated first: if the result is True, Python does not (and need not)
evaluate the expression on the right — this is called short-circuit evaluation. Similarly, for the and operator, if the
expression on the left yields False, Python does not evaluate the expression on the right.
So there are no unnecessary evaluations.
A truth table is a small table that allows us to list all the possible inputs, and to give the results for the logical operators.
Because the and and or operators each have two operands, there are only four rows in a truth table that describes the
semantics of and.
a b a and b
False False False
False True False
True False False
True True True
In a Truth Table, we sometimes use T and F as shorthand for the two Boolean values: here is the truth table describing
or:
a b a or b
F F F
F T T
T F T
T T T
The third logical operator, not, only takes a single operand, so its truth table only has two rows:
a not a
F T
T F
A set of rules for simplifying and rearranging expressions is called an algebra. For example, we are all familiar with
school algebra rules, such as:
n * 0 == 0
Here we see a different algebra — the Boolean algebra — which provides rules for working with Boolean values.
First, the and operator:
x or False == x
False or x == x
y or x == x or y
x or True == True
True or x == True
x or x == x
3.2. Conditionals 33
How to Think Like a Computer Scientist: Learning with Python 3 Documentation, Release 3rd
Edition
not (not x) == x
In order to write useful programs, we almost always need the ability to check conditions and change the behavior of
the program accordingly. Conditional statements give us this ability. The simplest form is the if statement:
1 if x % 2 == 0:
2 print(x, " is even.")
3 print("Did you know that 2 is the only even number that is prime?")
4 else:
5 print(x, " is odd.")
6 print("Did you know that multiplying two odd numbers " +
7 "always gives an odd result?")
The Boolean expression after the if statement is called the condition. If it is true, then all the indented statements get
executed. If not, then all the statements indented under the else clause get executed.
1 if <BOOLEAN EXPRESSION>:
2 <STATEMENTS_1> # Executed if condition evaluates to True
3 else:
4 <STATEMENTS_2> # Executed if condition evaluates to False
As with the function definition from the next chapter and other compound statements like for, the if statement
consists of a header line and a body. The header line begins with the keyword if followed by a Boolean expression
and ends with a colon (:).
The indented statements that follow are called a block. The first unindented statement marks the end of the block.
Each of the statements inside the first block of statements are executed in order if the Boolean expression evaluates to
True. The entire first block of statements is skipped if the Boolean expression evaluates to False, and instead all
the statements indented under the else clause are executed.
There is no limit on the number of statements that can appear under the two clauses of an if statement, but there has
to be at least one statement in each block. Occasionally, it is useful to have a section with no statements (usually as
a place keeper, or scaffolding, for code we haven’t written yet). In that case, we can use the pass statement, which
does nothing except act as a placeholder.
Another form of the if statement is one in which the else clause is omitted entirely. In this case, when the condition
evaluates to True, the statements are executed, otherwise the flow of execution continues to the statement after the
if.
1 if x < 0:
2 print("The negative number ", x, " is not valid here.")
3 x = 42
4 print("I've decided to use the number 42 instead.")
5
In this case, the print function that outputs the square root is the one after the if — not because we left a blank line,
but because of the way the code is indented. Note too that the function call math.sqrt(x) will give an error unless
3.2. Conditionals 35
How to Think Like a Computer Scientist: Learning with Python 3 Documentation, Release 3rd
Edition
we have an import math statement, usually placed near the top of our script.
Python terminology
Python documentation sometimes uses the term suite of statements to mean what we have called a block here. They
mean the same thing, and since most other languages and computer scientists use the word block, we’ll stick with that.
Notice too that else is not a statement. The if statement has two clauses, one of which is the (optional) else
clause.
Sometimes there are more than two possibilities and we need more than two branches. One way to express a compu-
tation like that is a chained conditional:
1 if x < y:
2 <STATEMENTS_A>
3 elif x > y:
4 <STATEMENTS_B>
5 else: # x == y
6 <STATEMENTS_C>
elif is an abbreviation of else if. Again, exactly one branch will be executed. There is no limit of the number of
elif statements but only a single (and optional) final else statement is allowed and it must be the last branch in the
statement:
1 if choice == "a":
2 function_one()
3 elif choice == "b":
4 function_two()
5 elif choice == "c":
6 function_three()
7 else:
8 print("Invalid choice.")
Each condition is checked in order. If the first is false, the next is checked, and so on. If one of them is true, the
corresponding branch executes, and the statement ends. Even if more than one condition is true, only the first true
branch executes.
One conditional can also be nested within another. (It is the same theme of composability, again!) We could have
written the previous example as follows:
1 if x < y:
2 <STATEMENTS_A>
3 else:
4 if x > y:
5 <STATEMENTS_B>
6 else:
7 <STATEMENTS_C>
3.2. Conditionals 37
How to Think Like a Computer Scientist: Learning with Python 3 Documentation, Release 3rd
Edition
The outer conditional contains two branches. The second branch contains another if statement, which has two
branches of its own. Those two branches could contain conditional statements as well.
Although the indentation of the statements makes the structure apparent, nested conditionals very quickly become very
difficult to read. In general, it is a good idea to avoid them when we can.
Logical operators often provide a way to simplify nested conditional statements. For example, we can rewrite the
following code using a single conditional:
The print function is called only if we make it past both the conditionals, so instead of the above which uses two
if statements each with a simple condition, we could make a more complex condition using the and operator. Now
we only need a single if statement:
Each of the six relational operators has a logical opposite: for example, suppose we can get a driving licence when our
age is greater or equal to 18, we can not get the driving licence when we are less than 18.
Notice that the opposite of >= is <.
Understanding these logical opposites allows us to sometimes get rid of not operators. not operators are often quite
difficult to read in computer code, and our intentions will usually be clearer if we can eliminate them.
For example, if we wrote this Python:
it would probably be clearer to use the simplification laws, and to write instead:
Two powerful simplification laws (called de Morgan’s laws) that are often helpful when dealing with complicated
Boolean expressions are:
For example, suppose we can slay the dragon only if our magic lightsabre sword is charged to 90% or higher, and we
have 100 or more energy units in our protective shield. We find this fragment of Python code in the game:
de Morgan’s laws together with the logical opposites would let us rework the condition in a (perhaps) easier to under-
stand way like this:
We could also get rid of the not by swapping around the then and else parts of the conditional. So here is a third
version, also equivalent:
This version is probably the best of the four, because it very closely matches the initial English statement. Clarity of
our code (for other humans), and making it easy to see that the code does what was expected should always be highest
priority.
As our programming skills develop we’ll find we have more than one way to solve any problem. So good programs
are designed. We make choices that favour clarity, simplicity, and elegance. The job title software architect says a
lot about what we do — we are architects who engineer our products to balance beauty, functionality, simplicity and
clarity in our creations.
Tip: Once our program works, we should play around a bit trying to polish it up. Write good comments. Think about
whether the code would be clearer with different variable names. Could we have done it more elegantly? Should we
rather use a function? Can we simplify the conditionals?
We think of our code as our creation, our work of art! We make it great.
3.2. Conditionals 39
How to Think Like a Computer Scientist: Learning with Python 3 Documentation, Release 3rd
Edition
3.3 Iteration
Computers are often used to automate repetitive tasks. Repeating identical or similar tasks without making errors is
something that computers do well and people do poorly.
Repeated execution of a set of statements is called iteration. Because iteration is so common, Python provides several
language features to make it easier. We’ve already seen the for statement. This is the form of iteration you’ll likely
be using most often. But here we’re going to look at the while statement — another way to have your program do
iteration, useful in slightly different circumstances.
Before we do that, let’s just review a few ideas. . .
3.3.1 Assignment
As we have mentioned previously, it is legal to make more than one assignment to the same variable. A new assignment
makes an existing variable refer to a new value (and stop referring to the old value).
1 airtime_remaining = 15
2 print(airtime_remaining)
3 airtime_remaining = 7
4 print(airtime_remaining)
15
7
because the first time airtime_remaining is printed, its value is 15, and the second time, its value is 7.
It is especially important to distinguish between an assignment statement and a Boolean expression that tests for
equality. Because Python uses the equal token (=) for assignment, it is tempting to interpret a statement like a = b
as a Boolean test. Unlike mathematics, it is not! Remember that the Python token for the equality operator is ==.
Note too that an equality test is symmetric, but assignment is not. For example, if a == 7 then 7 == a. But in
Python, the statement a = 7 is legal and 7 = a is not.
In Python, an assignment statement can make two variables equal, but because further assignments can change either
of them, they don’t have to stay that way:
1 a = 5
2 b = a # After executing this line, a and b are now equal
3 a = 3 # After executing this line, a and b are no longer equal
The third line changes the value of a but does not change the value of b, so they are no longer equal. (In some
programming languages, a different symbol is used for assignment, such as <- or :=, to avoid confusion. Some
people also think that variable was an unfortunae word to choose, and instead we should have called them assignables.
Python chooses to follow common terminology and token usage, also found in languages like C, C++, Java, and C#,
so we use the tokens = for assignment, == for equality, and we talk of variables.
When an assignment statement is executed, the right-hand side expression (i.e. the expression that comes after the
assignment token) is evaluated first. This produces a value. Then the assignment is made, so that the variable on the
left-hand side now refers to the new value.
One of the most common forms of assignment is an update, where the new value of the variable depends on its old
value. Deduct 40 cents from my airtime balance, or add one run to the scoreboard.
1 n = 5
2 n = 3 * n + 1
Line 2 means get the current value of n, multiply it by three and add one, and assign the answer to n, thus making n
refer to the value. So after executing the two lines above, n will point/refer to the integer 16.
If you try to get the value of a variable that has never been assigned to, you’ll get an error:
>>> w = x + 1
Traceback (most recent call last):
File "<interactive input>", line 1, in
NameError: name 'x' is not defined
Before you can update a variable, you have to initialize it to some starting value, usually with a simple assignment:
1 runs_scored = 0
2 ...
3 runs_scored = runs_scored + 1
Line 3 — updating a variable by adding 1 to it — is very common. It is called an increment of the variable; subtracting
1 is called a decrement. Sometimes programmers also talk about bumping a variable, which means the same as
incrementing it by 1. This is commonly done with the += operator.
1 runs_scored = 0
2 ...
3 runs_scored += 1
Recall that the for loop processes each item in a list. Each item in turn is (re-)assigned to the loop variable, and the
body of the loop is executed. We saw this example before:
Running through all the items in a list is called traversing the list, or traversal.
Let us write some code now to sum up all the elements in a list of numbers. Do this by hand first, and try to isolate
exactly what steps you take. You’ll find you need to keep some “running total” of the sum so far, either on a piece of
paper, in your head, or in your calculator. Remembering things from one step to the next is precisely why we have
variables in a program: so we’ll need some variable to remember the “running total”. It should be initialized with a
value of zero, and then we need to traverse the items in the list. For each item, we’ll want to update the running total
by adding the next number to it.
3.3. Iteration 41
How to Think Like a Computer Scientist: Learning with Python 3 Documentation, Release 3rd
Edition
Here is a fragment of code that demonstrates the use of the while statement:
1 while <CONDITION>:
2 <STATEMENT>
1 n = 6
2
3 current_sum = 0
4 i = 0
5 while i <= n:
6 current_sum += i
7 i += 1
8 print(current_sum)
You can almost read the while statement as if it were English. It means, while i is less than or equal to n, continue
executing the body of the loop. Within the body, each time, increment i. When i passes n, return your accumulated
sum. In other words: while <CONDITION> is True, <STATEMENT> is executed. Of course, this example could be
written more concisely as sum(range(n + 1)) because the function sum already exists.
More formally, here is precise flow of execution for a while statement:
• Evaluate the condition at line 5, yielding a value which is either False or True.
• If the value is False, exit the while statement and continue execution at the next statement (line 8 in this
case).
• If the value is True, execute each of the statements in the body (lines 6 and 7) and then go back to the while
statement at line 5.
The body consists of all of the statements indented below the while keyword.
Notice that if the loop condition is False the first time we get loop, the statements in the body of the loop are never
executed.
The body of the loop should change the value of one or more variables so that eventually the condition becomes false
and the loop terminates. Otherwise the loop will repeat forever, which is called an infinite loop.
In the case here, we can prove that the loop terminates because we know that the value of n is finite, and we can see
that the value of i increments each time through the loop, so eventually it will have to exceed n. In other cases it is
not so easy, maybe even impossible, to tell if the loop will ever terminate.
What you will notice here is that the while loop is more work for you — the programmer — than the equivalent
for loop. When using a while loop one has to manage the loop variable yourself: give it an initial value, test for
completion, and then make sure you change something in the body so that the loop terminates. By comparison, here
is an equivalent snippet that uses for instead:
1 n = 6
2
3 current_sum = 0
4 for i in range(n+1):
5 current_sum += i
6 print(current_sum)
Notice the slightly tricky call to the range function — we had to add one onto n, because range generates its list
up to but excluding the value you give it. It would be easy to make a programming mistake and overlook this.
So why have two kinds of loop if for looks easier? This next example shows a case where we need the extra power
that we get from the while loop.
Let’s look at a simple sequence that has fascinated and foxed mathematicians for many years. They still cannot answer
even quite simple questions about this.
The “computational rule” for creating the sequence is to start from some given n, and to generate the next term of
the sequence from n, either by halving n, (whenever n is even), or else by multiplying it by three and adding 1. The
sequence terminates when n reaches 1.
This Python snippet captures that algorithm:
1 n = 1027371
2
3 while n != 1:
4 print(n, end=", ")
5 if n % 2 == 0: # n is even
6 n = n // 2
7 else: # n is odd
8 n = n * 3 + 1
9 print(n, end=".\n")
Notice first that the print function on line 4 has an extra argument end=", ". This tells the print function to
follow the printed string with whatever the programmer chooses (in this case, a comma followed by a space), instead
of ending the line. So each time something is printed in the loop, it is printed on the same output line, with the numbers
separated by commas. The call to print(n, end=".\n") at line 9 after the loop terminates will then print the
final value of n followed by a period and a newline character. (You’ll cover the \n (newline character) later).
The condition for continuing with this loop is n != 1, so the loop will continue running until it reaches its termination
condition, (i.e. n == 1).
Each time through the loop, the program outputs the value of n and then checks whether it is even or odd. If it is even,
the value of n is divided by 2 using integer division. If it is odd, the value is replaced by n * 3 + 1.
Since n sometimes increases and sometimes decreases, there is no obvious proof that n will ever reach 1, or that the
program terminates. For some particular values of n, we can prove termination. For example, if the starting value is
a power of two, then the value of n will be even each time through the loop until it reaches 1. The previous example
ends with such a sequence, starting with 16.
See if you can find a small starting number that needs more than a hundred steps before it terminates.
Particular values aside, the interesting question was first posed by a German mathematician called Lothar Collatz: the
Collatz conjecture (also known as the 3n + 1 conjecture), is that this sequence terminates for all positive values of n.
So far, no one has been able to prove it or disprove it! (A conjecture is a statement that might be true, but nobody
knows for sure.)
Think carefully about what would be needed for a proof or disproof of the conjecture “All positive integers will
eventually converge to 1 using the Collatz rules”. With fast computers we have been able to test every integer up to
very large values, and so far, they have all eventually ended up at 1. But who knows? Perhaps there is some as-yet
untested number which does not reduce to 1.
You’ll notice that if you don’t stop when you reach 1, the sequence gets into its own cyclic loop: 1, 4, 2, 1, 4, 2, 1, 4
. . . So one possibility is that there might be other cycles that we just haven’t found yet.
Wikipedia has an informative article about the Collatz conjecture. The sequence also goes under other names (Hail-
stone sequence, Wonderous numbers, etc.), and you’ll find out just how many integers have already been tested by
computer, and found to converge!
3.3. Iteration 43
How to Think Like a Computer Scientist: Learning with Python 3 Documentation, Release 3rd
Edition
Use a for loop if you know, before you start looping, the maximum number of times that you’ll need to execute the
body. For example, if you’re traversing a list of elements, you know that the maximum number of loop iterations you
can possibly need is “all the elements in the list”. Or if you need to print the 12 times table, we know right away how
many times the loop will need to run.
So any problem like “iterate this weather model for 1000 cycles”, or “search this list of words”, “find all prime numbers
up to 10000” suggest that a for loop is best.
By contrast, if you are required to repeat some computation until some condition is met, and you cannot calculate in
advance when (of if) this will happen, as we did in this 3n + 1 problem, you’ll need a while loop.
We call the first case definite iteration — we know ahead of time some definite bounds for what is needed. The latter
case is called indefinite iteration — we’re not sure how many iterations we’ll need — we cannot even establish an
upper bound!
To write effective computer programs, and to build a good conceptual model of program execution, a programmer
needs to develop the ability to trace the execution of a computer program. Tracing involves becoming the computer
and following the flow of execution through a sample program run, recording the state of all variables and any output
the program generates after each instruction is executed.
To understand this process, let’s trace the call to the collatz code above with n = 3 from the previous section. At the
start of the trace, we have a variable, n, with an initial value of 3. Since 3 is not equal to 1, the while loop body is
executed. 3 is printed and 3 % 2 == 0 is evaluated. Since it evaluates to False, the else branch is executed and
3 * 3 + 1 is evaluated and assigned to n.
To keep track of all this as you hand trace a program, make a column heading on a piece of paper for each variable
created as the program runs and another one for output. Our trace so far would look something like this:
Since 10 != 1 evaluates to True, the loop body is again executed, and 10 is printed. 10 % 2 == 0 is true, so the
if branch is executed and n becomes 5. By the end of the trace we have:
Tracing can be a bit tedious and error prone (that’s why we get computers to do this stuff in the first place!), but it is
an essential skill for a programmer to have. From this trace we can learn a lot about the way our code works. We can
observe that as soon as n becomes a power of 2, for example, the program will require log2 (n) executions of the loop
body to complete. We can also see that the final 1 will not be printed as output within the body of the loop, which is
why we put the special print function at the end.
The following snippet counts the number of decimal digits in a positive integer:
1 n = 3029
2 count = 0
3 while n != 0:
4 count = count + 1
5 n = n // 10
6 print(count)
1 n = 2574301453
2 count = 0
3 while n > 0:
4 digit = n % 10
5 if digit == 0 or digit == 5:
6 count = count + 1
7 n = n // 10
8 print(count)
Notice, however, that if n = 0 this snippet will not print 1 as answer. Explain why. Do you think this is a bug in the
code, or a bug in the specifications, or our expectations?
Python comes with extensive documentation for all its built-in functions, and its libraries. Different systems have
different ways of accessing this help. See for example https://docs.python.org/3/library/stdtypes.html#typesseq-range
Notice the square brackets in the description of the arguments. These are examples of meta-notation — notation that
describes Python syntax, but is not part of it. The square brackets in this documentation mean that the argument is
optional — the programmer can omit it. So what this first line of help tells us is that range must always have a stop
argument, but it may have an optional start argument (which must be followed by a comma if it is present), and it
can also have an optional step argument, preceded by a comma if it is present.
The examples from help show that range can have either 1, 2 or 3 arguments. The list can start at any starting value,
and go up or down in increments other than 1. The documentation here also says that the arguments must be integers.
Other meta-notation you’ll frequently encounter is the use of bold and italics. The bold means that these are tokens —
keywords or symbols — typed into your Python code exactly as they are, whereas the italic terms stand for “something
of this type”. So the syntax description
for variable in list :
means you can substitute any legal variable and any legal list when you write your Python code.
This (simplified) description of the print function, shows another example of meta-notation in which the ellipses
(...) mean that you can have as many objects as you like (even zero), separated by commas:
print( [object, . . . ] )
Meta-notation gives us a concise and powerful way to describe the pattern of some syntax or feature.
3.3. Iteration 45
How to Think Like a Computer Scientist: Learning with Python 3 Documentation, Release 3rd
Edition
3.3.9 Tables
One of the things loops are good for is generating tables. Before computers were readily available, people had to
calculate logarithms, sines and cosines, and other mathematical functions by hand. To make that easier, mathematics
books contained long tables listing the values of these functions. Creating the tables was slow and boring, and they
tended to be full of errors.
When computers appeared on the scene, one of the initial reactions was, “This is great! We can use the computers to
generate the tables, so there will be no errors.” That turned out to be true (mostly) but shortsighted. Soon thereafter,
computers and calculators were so pervasive that the tables became obsolete.
Well, almost. For some operations, computers use tables of values to get an approximate answer and then perform
computations to improve the approximation. In some cases, there have been errors in the underlying tables, most
famously in the table the Intel Pentium processor chip used to perform floating-point division.
Although a log table is not as useful as it once was, it still makes a good example of iteration. The following program
outputs a sequence of values in the left column and 2 raised to the power of that value in the right column:
The string "\t" represents a tab character. The backslash character in "\t" indicates the beginning of an escape
sequence. Escape sequences are used to represent invisible characters like tabs and newlines. The sequence \n
represents a newline.
An escape sequence can appear anywhere in a string; in this example, the tab escape sequence is the only thing in the
string. How do you think you represent a backslash in a string?
As characters and strings are displayed on the screen, an invisible marker called the cursor keeps track of where the
next character will go. After a print function, the cursor normally goes to the beginning of the next line.
The tab character shifts the cursor to the right until it reaches one of the tab stops. Tabs are useful for making columns
of text line up, as in the output of the previous program:
0 1
1 2
2 4
3 8
4 16
5 32
6 64
7 128
8 256
9 512
10 1024
11 2048
12 4096
Because of the tab characters between the columns, the position of the second column does not depend on the number
of digits in the first column.
A two-dimensional table is a table where you read the value at the intersection of a row and a column. A multiplication
table is a good example. Let’s say you want to print a multiplication table for the values from 1 to 6.
A good way to start is to write a loop that prints the multiples of 2, all on one line:
Here we’ve used the range function, but made it start its sequence at 1. As the loop executes, the value of i changes
from 1 to 6. When all the elements of the range have been assigned to i, the loop terminates. Each time through the
loop, it displays the value of 2 * i, followed by three spaces.
Again, the extra end=" " argument in the print function suppresses the newline, and uses three spaces instead.
After the loop completes, the call to print at line 3 finishes the current line, and starts a new line.
The output of the program is:
2 4 6 8 10 12
So far, so good. The next step is to encapsulate and generalize. We will continue this topic in the next chapter.
The break statement is used to immediately leave the body of its loop. The next statement to be executed is the first
one after the body:
This prints:
12
16
done
3.3. Iteration 47
How to Think Like a Computer Scientist: Learning with Python 3 Documentation, Release 3rd
Edition
Sometimes we’d like to have the middle-test loop with the exit test in the middle of the body, rather than at the
beginning or at the end. Or a post-test loop that puts its exit test as the last thing in the body. Other languages
have different syntax and keywords for these different flavours, but Python just uses a combination of while and if
<CONDITION>: break to get the job done.
A typical example is a problem where the user has to input numbers to be summed. To indicate that there are no more
inputs, the user enters a special value, often the value -1, or the empty string. This needs a middle-exit loop pattern:
input the next number, then test whether to exit, or else process the number:
1 total = 0
2 while True:
3 response = input("Enter the next number. (Leave blank to end)")
4 if response == "" or response == "-1":
5 break
6 total += int(response)
7 print("The total of the numbers you entered is ", total)
Convince yourself that this fits the middle-exit loop flowchart: line 3 does some useful work, lines 4 and 5 can exit the
loop, and if they don’t line 6 does more useful work before the next iteration starts.
The while bool-expr: uses the Boolean expression to determine whether to iterate again. True is a trivial
Boolean expression, so while True: means always do the loop body again. This is a language idiom — a conven-
tion that most programmers will recognize immediately. Since the expression on line 2 will never terminate the loop,
(it is a dummy test) the programmer must arrange to break (or return) out of the loop body elsewhere, in some other
way (i.e. in lines 4 and 5 in this sample). A clever compiler or interpreter will understand that line 2 is a fake test that
must always succeed, so it won’t even generate a test, and our flowchart never even put the diamond-shape dummy
test box at the top of the loop!
Similarly, by just moving the if condition: break to the end of the loop body we create a pattern for a post-
test loop. Post-test loops are used when you want to be sure that the loop body always executes at least once (because
the first test only happens at the end of the execution of the first loop body). This is useful, for example, if we want to
play an interactive game against the user — we always want to play at least one game:
1 while True:
2 play_the_game_once()
3 response = input("Play again? (yes or no)")
4 if response != "yes":
5 break
6 print("Goodbye!")
Hint: Think about where you want the exit test to happen
Once you’ve recognized that you need a loop to repeat something, think about its terminating condition — when will
I want to stop iterating? Then figure out whether you need to do the test before starting the first (and every other)
iteration, or at the end of the first (and every other) iteration, or perhaps in the middle of each iteration. Interactive
programs that require input from the user or read from files often need to exit their loops in the middle or at the end
of an iteration, when it becomes clear that there is no more data to process, or the user doesn’t want to play our game
anymore.
3.3.13 An example
5 guesses = 0
6 message = ""
7
8 while True:
9 guess = int(input(message + "\nGuess my number between 1 and 1000: "))
10 guesses += 1
11 if guess > number:
12 message += str(guess) + " is too high.\n"
13 elif guess < number:
14 message += str(guess) + " is too low.\n"
15 else:
16 break
17
This program makes use of the mathematical law of trichotomy (given real numbers a and b, exactly one of these
three must be true: a > b, a < b, or a == b).
At line 18 there is a call to the input function, but we don’t do anything with the result, not even assign it to a variable.
This is legal in Python. Here it has the effect of popping up the input dialog window and waiting for the user to respond
before the program terminates. Programmers often use the trick of doing some extra input at the end of a script, just
to keep the window open.
Also notice the use of the message variable, initially an empty string, on lines 6, 12 and 14. Each time through the
loop we extend the message being displayed: this allows us to display the program’s feedback right at the same place
as we’re asking for the next guess.
3.3. Iteration 49
How to Think Like a Computer Scientist: Learning with Python 3 Documentation, Release 3rd
Edition
This is a control flow statement that causes the program to immediately skip the processing of the rest of the body of
the loop, for the current iteration. But the loop still carries on running for its remaining iterations:
This prints:
12
16
24
30
done
We’ve already seen lists of names and lists of numbers in Python. We’re going to peek ahead in the textbook a little,
and show a more advanced way of representing our data. Making a pair of things in Python is as simple as putting
them into parentheses, like this:
Here is a quick sample of things we can do with structured data like this. First, print all the celebs:
1 print(celebs)
2 print(len(celebs))
Notice that the celebs list has just 3 elements, each of them pairs.
Now we print the names of those celebrities born before 1980:
Brad Pitt
Jack Nicholson
This demonstrates something we have not seen yet in the for loop: instead of using a single loop control variable,
we’ve used a pair of variable names, (name, year), instead. The loop is executed three times — once for each
pair in the list, and on each iteration both the variables are assigned values from the pair of data that is being handled.
Now we’ll come up with an even more adventurous list of structured data. In this case, we have a list of students. Each
student has a name which is paired up with another list of subjects that they are enrolled for:
1 students = [
2 ("John", ["CompSci", "Physics"]),
3 ("Vusi", ["Maths", "CompSci", "Stats"]),
4 ("Jess", ["CompSci", "Accounting", "Economics", "Management"]),
5 ("Sarah", ["InfSys", "Accounting", "Economics", "CommLaw"]),
6 ("Zuki", ["Sociology", "Economics", "Law", "Stats", "Music"])]
Here we’ve assigned a list of five elements to the variable students. Let’s print out each student name, and the
number of subjects they are enrolled for:
Now we’d like to ask how many students are taking CompSci. This needs a counter, and for each student we need a
second loop that tests each of the subjects in turn:
3.3. Iteration 51
How to Think Like a Computer Scientist: Learning with Python 3 Documentation, Release 3rd
Edition
1 counter = 0
2 for name, subjects in students:
3 if "CompSci" in subjects:
4 counter += 1
You should set up a list of your own data that interests you — perhaps a list of your CDs, each containing a list of
song titles on the CD, or a list of movie titles, each with a list of movie stars who acted in the movie. You could then
ask questions like “Which movies starred Angelina Jolie?”
Loops are often used in programs that compute numerical results by starting with an approximate answer and iteratively
improving it.
For example, before we had calculators or computers, people needed to calculate square roots manually. Newton used
a particularly good method (there is some evidence that this method was known many years before). Suppose that you
want to know the square root of n. If you start with almost any approximation, you can compute a better approximation
(closer to the actual answer) with the following formula:
Repeat this calculation a few times using your calculator. Can you see why each iteration brings your estimate a little
closer? One of the amazing properties of this particular algorithm is how quickly it converges to an accurate answer
— a great advantage for doing it manually.
By using a loop and repeating this formula until the better approximation gets close enough to the previous one, we
can write a function for computing the square root. (In fact, this is how your calculator finds square roots — it may
have a slightly different formula and method, but it is also based on repeatedly improving its guesses.)
This is an example of an indefinite iteration problem: we cannot predict in advance how many times we’ll want to
improve our guess — we just want to keep getting closer and closer. Our stopping condition for the loop will be when
our old guess and our improved guess are “close enough” to each other.
Ideally, we’d like the old and new guess to be exactly equal to each other when we stop. But exact equality is a tricky
notion in computer arithmetic when real numbers are involved. Because real numbers are not represented absolutely
accurately (after all, a number like pi or the square root of two has an infinite number of decimal places because it
is irrational), we need to formulate the stopping test for the loop by asking “is a close enough to b”? This stopping
condition can be coded like this:
1 threshold = 0.001
2 if abs(a-b) < threshold: # Make this smaller for better accuracy
3 break
Notice that we take the absolute value of the difference between a and b!
This problem is also a good example of when a middle-exit loop is appropriate:
1 n = 8
2 threshold = 0.001
3 approximation = n/2 # Start with some or other guess at the answer
4 while True:
5 better = (approximation + n/approximation)/2
6 if abs(approximation - better) < threshold:
7 print(better)
(continues on next page)
See if you can improve the approximations by changing the stopping condition. Also, step through the algorithm
(perhaps by hand, using your calculator) to see how many iterations were needed before it achieved this level of
accuracy for sqrt(25).
3.3.18 Algorithms
Newton’s method is an example of an algorithm: it is a mechanical process for solving a category of problems (in this
case, computing square roots).
Some kinds of knowledge are not algorithmic. For example, learning dates from history or your multiplication tables
involves memorization of specific solutions.
But the techniques you learned for addition with carrying, subtraction with borrowing, and long division are all al-
gorithms. Or if you are an avid Sudoku puzzle solver, you might have some specific set of steps that you always
follow.
One of the characteristics of algorithms is that they do not require any intelligence to carry out. They are mechanical
processes in which each step follows from the last according to a simple set of rules. And they’re designed to solve a
general class or category of problems, not just a single problem.
Understanding that hard problems can be solved by step-by-step algorithmic processes (and having technology to
execute these algorithms for us) is one of the major breakthroughs that has had enormous benefits. So while the
execution of the algorithm may be boring and may require no intelligence, algorithmic or computational thinking —
i.e. using algorithms and automation as the basis for approaching problems — is rapidly transforming our society.
Some claim that this shift towards algorithmic thinking and processes is going to have even more impact on our
society than the invention of the printing press. And the process of designing algorithms is interesting, intellectually
challenging, and a central part of what we call programming.
Some of the things that people do naturally, without difficulty or conscious thought, are the hardest to express algo-
rithmically. Understanding natural language is a good example. We all do it, but so far no one has been able to explain
how we do it, at least not in the form of a step-by-step mechanical algorithm.
These are small summaries of ideas, tips, and commonly seen errors that might be helpful to those beginning Python.
We often want to know if some condition holds for any item in a list, e.g. “does the list have any odd numbers?” This
is a common mistake:
3 # Buggy version
4 for number in numbers:
5 if number % 2 == 1:
6 print(True)
7 break
8 else:
(continues on next page)
Can we spot two problems here? As soon as we execute a break, we’ll leave the loop. So the logic of saying “If I
find an odd number I can return True” is fine. However, we cannot return False after only looking at one item —
we can only return False if we’ve been through all the items, and none of them are odd. So line 10 should not be
there, and lines 8 and 9 have to be outside the loop. Here is a corrected version:
We’ll see This “eureka”, or “short-circuit” style of breaking from a loop as soon as we are certain what the outcome
will be again later.
The performance disadvantage of this one is that it traverses the whole list, even if it knows the outcome very early on.
The code in lines 6-9 can also be tightened up. The expression count > 0 itself represents a Boolean value, either
True or False (we can say it ‘evaluates’ to either True or False). That True/False value can be used directly
in the print statement. So we could cut out that code and simply have the following:
Although this code is tighter, it is not as nice as the one that did the short-circuit return as soon as the first odd number
was found.
Even shorter:
Exercise time:
• How would we adapt this to print True if all the numbers are odd? Can you still use a short-circuit style?
• How would we adapt it to print True if at least three of the numbers are odd? Short-circuit the traversal when
the third odd number is found — don’t traverse the whole list unless we have to.
Computers are useful because they can repeat computation, accurately and fast. So loops are going to be a central
feature of almost all programs you encounter.
Here are two functions that both generate ten million random numbers, and return the sum of the numbers. They both
work.
1 import random
2 joe = random.Random()
3
4 # Version 1
5 # Build a list of random numbers, then sum them
6 numbers = []
7 for _ in range(10000000):
8 num = joe.randrange(1000) # Generate one random number
9 numbers.append(num) # Save it in our list, see the next
˓→chapter
10
11 tot = sum(numbers)
12 print(tot)
13
What reasons are there for preferring the second version here? (Hint: open a tool like the Performance Monitor on
your computer, and watch the memory usage. How big can you make the list before you get a fatal memory error in
the first version?)
In a similar way, when working with files, we often have an option to read the whole file contents into a single string,
or we can read one line at a time and process each line as we read it. Line-at-a-time is the more traditional and perhaps
safer way to do things — you’ll be able to work comfortably no matter how large the file is. (And, of course, this mode
of processing the files was essential in the old days when computer memories were much smaller.) But you may find
whole-file-at-once is sometimes more convenient!
3.4.3 Glossary
attribute Some state or value that belongs to a particular object. For example, tess has a color.
canvas A surface within a window where drawing takes place.
control flow See flow of execution.
for loop A statement in Python for convenient repetition of statements in the body of the loop.
loop body Any number of statements nested inside a loop. The nesting is indicated by the fact that the statements are
indented under the for loop statement.
loop variable A variable used as part of a for loop. It is assigned a different value on each iteration of the loop.
instance An object of a certain type, or class. tess and alex are different instances of the class Turtle.
method A function that is attached to an object. Invoking or activating the method causes the object to respond in
some way, e.g. forward is the method when we say tess.forward(100).
invoke An object has methods. We use the verb invoke to mean activate the method. Invoking a method is done
by putting parentheses after the method name, with some possible arguments. So tess.forward() is an
invocation of the forward method.
module A file containing Python definitions and statements intended for use in other Python programs. The contents
of a module are made available to the other program by using the import statement.
object A “thing” to which a variable can refer. This could be a screen window, or one of the turtles we have created.
range A built-in function in Python for generating sequences of integers. It is especially useful when we need to write
a for loop that executes a fixed number of times.
terminating condition A condition that occurs which causes a loop to stop repeating its body. In the for loops we
saw in this chapter, the terminating condition has been when there are no more elements to assign to the loop
variable.
block A group of consecutive statements with the same indentation.
body The block of statements in a compound statement that follows the header.
Boolean algebra Some rules for rearranging and reasoning about Boolean expressions.
Boolean expression An expression that is either true or false.
Thinking like a scientist involves looking for patterns and relationships. In the code above, we’ve done that to some
extent. We did not just draw four sides. Instead, we spotted that we could draw the rectangle as two halves, and used
a loop to repeat that pattern twice.
But now we might spot that a square is a special kind of rectangle. We already have a function that draws a rectangle,
so we can use that to draw our square.
In order to ensure that a function is defined before its first use, we have to know the order in which statements are
executed, which is called the flow of execution.
Execution always begins at the first statement of the program. Statements are executed one at a time, in order from top
to bottom.
Function definitions do not alter the flow of execution of the program, but remember that statements inside the function
are not executed until the function is called. Although it is not common, we can define one function inside another. In
this case, the inner definition isn’t executed until the outer function is called.
Function calls are like a detour in the flow of execution. Instead of going to the next statement, the flow jumps to the
first line of the called function, executes all the statements there, and then comes back to pick up where it left off.
66 Chapter 4. Functions
How to Think Like a Computer Scientist: Learning with Python 3 Documentation, Release 3rd
Edition
That sounds simple enough, until we remember that one function can call another. While in the middle of one function,
the program might have to execute the statements in another function. But while executing that new function, the
program might have to execute yet another function!
Fortunately, Python is adept at keeping track of where it is, so each time a function completes, the program picks up
where it left off in the function that called it. When it gets to the end of the program, it terminates.
What’s the moral of this sordid tale? When we read a program, don’t read from top to bottom. Instead, follow the flow
of execution.
As a simple example, let’s consider the following program:
1 import turtle
2
12 draw_square(tess, 50)
13
14 window.mainloop()
The Python interpreter reads this script line by line. At the first line the turtle module is imported. We then define
draw_square, which contains the instructions for a given turtle to draw a square. However, nothing happens yet.
We then go on to define a window, and our charming turtle tess. The next line calls ``draw_square,
asking tess to draw a square with sides of length 50. Finally, window.mainloop() actually runs these execu-
tions, and you will see tess draw a square on the screen.
Being able to trace your program is a valuable skill for a programmer.
Most functions require arguments: the arguments provide for generalization. For example, if we want to find the
absolute value of a number, we have to indicate what the number is. Python has a built-in function for computing the
absolute value:
>>> abs(5)
5
>>> abs(-5)
5
In this example, the arguments to the abs function are 5 and -5.
Some functions take more than one argument. For example the built-in function pow takes two arguments, the base
and the exponent. Inside the function, the values that are passed get assigned to variables called parameters.
>>> pow(2, 3)
8
>>> pow(7, 4)
2401
Another built-in function that takes more than one argument is max.
max can be passed any number of arguments, separated by commas, and will return the largest value passed. The
arguments can be either simple values or expressions. In the last example, 503 is returned, since it is larger than 33,
125, and 1.
All the functions in the previous section return values. Calling each of these functions generates a value, which we
usually assign to a variable or use as part of an expression.
1 biggest = max(3, 7, 2, 5)
2 x = abs(3 - 11) + 10
So an important difference between these functions and one like draw_square is that draw_square was not
executed because we wanted it to compute a value — on the contrary, we wrote draw_square because we wanted
it to execute a sequence of steps that caused the turtle to draw.
A function that returns a value is called a fruitful function in this book. The opposite of a fruitful function is
void function — one that is not executed for its resulting value, but is executed because it does something useful.
(Languages like Java, C#, C and C++ use the term “void function”, other languages like Pascal call it a procedure.)
Even though void functions are not executed for their resulting value, Python always wants to return something. So if
the programmer doesn’t arrange to return a value, Python will automatically return the value None.
How do we write our own fruitful function? In the exercises at the end of chapter 2 we saw the standard formula for
compound interest, which we’ll now write as a fruitful function:
7 a = p * (1 + r/n) ** (n*t)
8 return a # This is new, and makes the function fruitful.
9
68 Chapter 4. Functions
How to Think Like a Computer Scientist: Learning with Python 3 Documentation, Release 3rd
Edition
• The return statement is followed an expression (a in this case). This expression will be evaluated and returned
to the caller as the “fruit” of calling this function.
• We prompted the user for the principal amount. The type of toInvest is a string, but we need a number before
we can work with it. Because it is money, and could have decimal places, we’ve used the float type converter
function to parse the string and return a float.
• Notice how we entered the arguments for 8% interest, compounded 12 times per year, for 5 years.
• When we run this, we get the output
At the end of the period you’ll have 14898.457083
This is a bit messy with all these decimal places, but remember that Python doesn’t understand that we’re
working with money: it just does the calculation to the best of its ability, without rounding. Later we’ll see how
to format the string that is printed in such a way that it does get nicely rounded to two decimal places before
printing.
• The line toInvest = float(input("How much do you want to invest?")) also shows yet
another example of composition — we can call a function like float, and its arguments can be the results of
other function calls (like input) that we’ve called along the way.
Notice something else very important here. The name of the variable we pass as an argument — toInvest — has
nothing to do with the name of the parameter — p. It is as if p = toInvest is executed when final_amount is
called. It doesn’t matter what the value was named in the caller, in final_amount its name is p.
These short variable names are getting quite tricky, so perhaps we’d prefer one of these versions instead:
They all do the same thing. Use your judgement to write code that can be best understood by other humans! Short
variable names should generally be avoided, unless when short variables make more sense. This happens in particular
with mathematical equations, where it’s perfectly fine to use x, y, etc.
When we create a local variable inside a function, it only exists inside the function, and we cannot use it outside. For
example, consider again this function: