We’ve learned a lot of Python in the readings so far, but there are still a few
fundamental programming constructs we haven’t seen yet. This is the first of
two readings that cover loops, and we will also soon cover conditionals (if
statements).
What a loop is
One of the basic things that programs have to be able to do is to repeat a chunk of code over and over. Sometimes there is something that changes every time we execute the chunk of code, and sometimes there isn’t. For instance, we might want to print a greeting ten times. In that case, we would be executing the exact same code (print the greeting) ten times. Or we might want to print the numbers from 1 to 20, one per line. In that case, something would change each time (the number to print). Sometimes more than one thing changes each time.
In order to allow us to execute chunks of code over and over, programming languages like Python contain loop statements and syntax. Nearly every programming language has loop statements with special syntax, but unfortunately every language seems to choose different syntax for what is basically the same construct. Fortunately, Python’s loop syntax is simple and easy to pick up.
Python’s loop statements
Python has two kinds of loop statements: for
loops and while
loops. These
are named after the keywords for
and while
. In this reading we’ll teach
you about for
loops, because they are the most common kind of loop in Python
programs. We’ll teach you about while
loops in a couple of readings.
[1]
Loops and lists
We postponed discussing loops until we learned about lists for a good reason: loops are incredibly useful when used with lists. One common code pattern of a loop used with a list looks like this:
-
for each element in a list...
-
...do the following with the element,
-
...and repeat until all the elements in the list have been processed.
What we’ve just written is an example of what is called pseudocode. It’s like code, but written for the benefit of humans, not computers. It describes a computation in English with enough detail that it could in principle be converted to a programming language like Python. Writing pseudocode can be a powerful design technique for working out a solution to a programming problem before you start the actual coding. |
An example of this might be the following: for each element of the following list, print the element.
title_words = ['Monty', 'Python', 'and', 'the', 'Holy', 'Grail'] for word in title_words: print(word)
When run, this will print out:
Monty Python and the Holy Grail
one word per line.
for
loop syntax
The syntax of the for
loop is basically the following:
for <item> in <list>: <chunk of code>
Both for
and in
are keywords (reserved words). The <item>
is a variable
that will refer to a particular element in the list <list>
. The <list>
can
be either an actual list, a variable which refers to a list, or an expression
which evaluates to a list.
The colon character (:
) at the end of the for
line is required, much like
at the end of a def
line in a function definition.
The <chunk of code>
part is called a block; it consists of one or more
lines of Python code, all indented the same. [2]
The way the loop works is as follows.
-
The first element of the list
<list>
is assigned to the<item>
variable. -
The body of the loop is evaluated.
-
Then the next element of the list is assigned to the
<item>
variable and the body is evaluated again. -
This continues until there are no more elements in the list.
-
After the
for
loop has completed evaluating, Python goes on to the next line after the loop.
The thing that goes in the for <item> in <list>: <chunk of code> doesn’t actually have to be a list. There are many other things that can go
there, including strings and other data structures like tuples and dictionaries
we haven’t seen yet. Any Python value that is an iterable can go in that
place. An iterable basically means "something that can be looped over in a
|
A simple example
Let’s revisit the simple example above:
title_words = ['Monty', 'Python', 'and', 'the', 'Holy', 'Grail'] for word in title_words: print(word)
We know that this will print out the words in the list, one per line. But how does it actually work?
When the loop starts, the first element of the list, which is 'Monty'
, gets
assigned to the variable word
. Then the body prints that word. Then the
second element of the list ('Python'
) gets assigned to word
, the word gets
printed, and so on until all the words in the list have been printed. Once
there are no more words in the list to bind to word
, the for
loop has
finished executing.
So what Python ends up doing when it evaluates the loop is basically the following:
word = 'Monty' print(word) word = 'Python' print(word) word = 'and' print(word) ...
but it’s much easier and more concise to express this with the for
loop.
The list title_words
isn’t altered in the for
loop; Python simply fetches
its elements one at a time in order and assigns then to the word
variable.
There is no significance to the variable name word
either; we could call it
w
or xxx
if we wanted, but it’s a good idea to use meaningful variable
names where possible.
Multiline blocks
A for
loop block can consist of multiple lines, all indented the same. Let’s
extend our simple example:
title_words = ['Monty', 'Python', 'and', 'the', 'Holy', 'Grail'] for word in title_words: print(word) print('----')
This will print:
Monty ---- Python ---- and ---- the ---- Holy ---- Grail ----
After the block, the indentation has to go back to the previous level so Python knows that the block is finished:
title_words = ['Monty', 'Python', 'and', 'the', 'Holy', 'Grail'] for word in title_words: print(word) print('----') print('All done!')
Loop syntax errors
Forgetting the colon
A really, really common error is to forget to put the colon character at the
end of the for
line:
title_words = ['Monty', 'Python', 'and', 'the', 'Holy', 'Grail'] for word in title_words print(word)
Here’s what will happen:
for word in title_words ^ SyntaxError: invalid syntax
Like it or not, you have to put that colon in!
Bad indentation
If the for
loop block has more than one line, the lines have to be indented
exactly the same. Failure to do this gives you one of three syntax errors.
Too much indentation:
title_words = ['Monty', 'Python', 'and', 'the', 'Holy', 'Grail'] for word in title_words: print(word) print('----')
gives:
print('----') ^ IndentationError: unexpected indent
Too little indentation:
title_words = ['Monty', 'Python', 'and', 'the', 'Holy', 'Grail'] for word in title_words: print(word) print('----')
gives:
print('----') ^ IndentationError: unindent does not match any outer indentation level
Python knows that you are indenting less than the previous line, but this is
only legal when there is some other code with that indent level (like the for
line); here, there isn’t one.
These two syntax errors are pretty obvious. But there is one more which can be extremely hard to detect. Sometimes when you’re writing code in a text editor, the editor will use tab characters to indent code. Other times it might use spaces, or a combination of the two. If different lines in a block are indented using tabs on some lines and spaces on other lines, you can get syntax errors even if it looks like they’re indented exactly the same!
It’s hard to show you what this would look like, but let’s imagine that in your
editor, tab characters look like four space characters. We’ll write a tab
character like this: <tab>
so you can see them. Consider this code:
title_words = ['Monty', 'Python', 'and', 'the', 'Holy', 'Grail'] for word in title_words: print(word) <tab>print('----')
The code will look perfectly indented. But Python will give you a syntax error:
print('----') ^ TabError: inconsistent use of tabs and spaces in indentation
This is one reason why every Python style guide says not to use tab characters for indentation. [3]
See this video to get more insight about the tabs vs. spaces controversy.
Application: writing the sum
function
We’ve already seen the built-in sum
function:
temps = [59.6, 72.4, 68.5, 79.0, 66.4, 77.1, -126.0] avg_temp = sum(temps) / 7 print(avg_temp)
This prints:
42.42857142857143
Now that we know how to write loops, we can write sum
ourselves. Here’s the
first attempt.
def sum(nums): """Sum the elements of a list of numbers.""" sum_nums = 0 for n in nums: sum_nums = sum_nums + n return sum_nums
Built-in functions like |
Let’s test it:
temps = [59.6, 72.4, 68.5, 79.0, 66.4, 77.1, -126.0] avg_temp = sum(temps) / 7 print(avg_temp)
This prints:
42.42857142857143
so we’re good.
Aside: the +=
operator and friends
Look at the sum
function we wrote above, and in particular this line:
sum_nums = sum_nums + n
Lines of the form x = x + y
are extremely common in programming. The meaning
of this line is "add y
to the number x
". Since this is so common, there
is a shortcut operator that does the same thing, but more concisely. The
operator is called +=
(pronounced "plus-equals") and looks like this:
sum_nums += n
Similarly, there are other <op>=
operators such as -=
, *=
, /=
and so on
which work the same way. So x -= y
is the same as x = x - y
; x *= y
is
the same as x = x * y
etc.
We recommend that you use these operators instead of the longer forms for two reasons:
-
It’s shorter.
-
It’s easier to read once you get used to it.
sum
again
Let’s update our sum
function with this spiffy new operator:
def sum(nums): """Sum the elements of a list of numbers.""" sum_nums = 0 for n in nums: sum_nums += n return sum_nums
And that’s all we’ll say about this function!
Loop terminology
At this time, it’s appropriate to define some terms that are commonly used with loops:
- loop body
-
The block of code that is executed multiple times in a loop.
- iteration
-
A single pass through the loop body.
- iterate over
-
Go through a data structure (e.g. a list) element-by-element, executing the loop body on each element.
- iterable
-
A Python data structure (such as a list) that can be iterated over in a loop.
Don’t worry if these definitions don’t seem crystal clear to you at this point.
As we learn more about what kinds of data can be used in a for
loop it will
all become clear.
Loop pitfalls
In a for
loop body, it’s not a good idea to change either the loop variable
or the list being iterated over. The main reason is that what this does is
hard to predict unless you understand Python really well. Python is changing
the loop variable for you on every iteration of the loop body, so you shouldn’t
need to change it yourself. And if you change the list being iterated over,
the loop may finish earlier or later than you expected, or behave in other
non-intuitive ways.
There will be problems on the assignments exploring these pitfalls.
Loops and strings
We mentioned above that in the for
loop syntax, which we wrote as:
for <item> in <list>: <chunk of code>
the <list>
part could actually be things other than lists. One such thing is
a string. If you loop over a string in a for
loop, you are iterating over
the characters.
for char in 'Python': print(char)
This will print:
P y t h o n
In each iteration of the for
loop, the next character of the string Python
is assigned to the variable char
. (This will be a one-character string,
because that’s how Python represents characters.)
We already know that both lists and strings are what Python calls sequences,
so you might think that any Python sequence can be looped over in a for
loop.
And that is in fact the case. (We will see soon that even some non-sequences
can be looped over in a for
loop.)
Nested loops
You are allowed to put one for
loop inside another. This is called a "nested
loop" and is actually quite common. Here’s a simple example:
1title = ['Monty', 'Python']
2for word in title:
3 for char in word:
4 print(char)
The first for
loop starts on line 2. Its loop body consists of lines 3 and
4, which is also a for
loop. We say that the for
loop starting from line 2
is the "outer" for
loop and the one starting from line 3 is the "inner" for
loop. Notice that the loop body of the inner for
loop (line 4) is indented
twice: once because it’s in the loop body of the outer for
loop and once
because it’s also in the loop body of the inner for
loop.
In the first iteration of the outer for
loop, the variable word
is
'Monty'
. Then in the inner for
loop, the variable char
is 'M'
, then
'o'
, etc. Once all the characters in 'Monty'
have been processed, the
variable word
in the outer for
loop becomes 'Python'
, and then in the
inner for
loop the variable char
becomes 'P'
, 'y'
, etc.
Running this code gives this result:
M o n t y P y t h o n
We can write code that is inside the first loop but which comes after the nested loop. That code is executed once the nested loop is finished executing.
title = ['Monty', 'Python'] for word in title: for char in word: print(char) print('---') # executed after nested loop finishes
Running this code gives this result:
M o n t y --- P y t h o n ---
Coming up
We have more to say about loops, and in particular, Python’s other loop
construct, the while
loop. We’ll get to that shortly, but in the next
reading we will talk about conditionals (if
statements), another fundamental
building block of computer programs.
[End of reading]