Python
Python
Iteration
Iteration repeats the execution of a sequence of code. Iteration is useful for solving many programming
problems. Iteration and conditional execution form the basis for algorithm construction.
Listing 5.1 (counttofive.py) counts to five by printing a number on each output line.
print(1)
print(2)
print(3)
print(4)
print(5)
How would you write the code to count to 10,000? Would you copy, paste, and modify 10,000 printing
statements? You could, but that would be impractical! Counting is such a common activity, and
computers
routinely count up to very large values, so there must be a better way. What we really would like to
do is print the value of a variable (call it count), then increment the variable (count += 1), and repeat
this process until the variable is large enough (count == 5 or maybe count == 10000). This process of
executing the same section of code over and over is known as iteration, or looping. Python has two
different
statements, while and for, that enable iteration.
The while statement in Listing 5.2 (iterativecounttofive.py) repeatedly displays the variable count. The
print(count)
count += 1
After each redisplay of the variable count, the program increments it by one. Eventually (after five itera-
tions), the condition count <= 5 will no longer be true, and the block is no longer executed.
Unlike the approach taken in Listing 5.1 (counttofive.py), it is trivial to modify Listing 5.2
(iterativecounttofive.py)
The line
begins the while statement. The expression following the while keyword is the condition that
determines
if the statement block is executed or continues to execute. As long as the condition is true, the program
executes the code block over and over again. When the condition becomes false, the loop is finished. If
the
condition is false initially, the program will not execute the code block within the body of the loop at all.
The while statement has the general form:
condition
block
while :
• The condition determines whether the body will be (or will continue to be) executed. A colon (:)
• block is a block of one or more statements to be executed as long as the condition is true. As a block,
all the statements that comprise the block must be indented one level deeper than the line that begins
the while statement. The block technically is part of the while statement.
Except for the reserved word while instead of if, while statements look identical to if statements.
Sometimes beginning programmers confuse the two or accidentally type if when they mean while or
vice-versa. Usually the very different behavior of the two statements reveals the problem immediately;
however, sometimes, especially in nested, complex logic, this mistake can be hard to detect.
Figure 5.1 shows how program execution flows through Listing 5.2 (iterativecounttofive.py).
Is
count ≤ 5?
Print count’s
value
Set count
equal to 1
Start
Increment
count’s value
End
No
Yes
The executing program checks the condition before executing the while block and then checks the
condition again after executing the while block. As long as the condition remains truth, the program
repeatedly executes the code in the while block. If the condition initially is false, the program will not
execute the code within the while block. If the condition initially is true, the program executes the block
repeatedly until the condition becomes false, at which point the loop terminates.
Listing 5.3 (countup.py) counts up from zero as long as the user wishes to do so.
print(count)
Listing 5.4 (addnonnegatives.py) is a program that allows a user to enter any number of nonnegative
integers. When the user enters a negative value, the program no longer accepts input, and it displays
the
sum of all the nonnegative values. If a negative number is the first entry, the sum is zero.
• entry
In the beginning we initialize entry to zero for the sole reason that we want the condition entry >= 0
of the while statement to be true initially. If we fail to initialize entry, the program will produce a
run-time error when it attempts to compare entry to zero in the while condition. The entry variable
holds the number entered by the user. Its value can change each time through the loop.
• sum
The variable sum is known as an accumulator because it accumulates each value the user enters. We
initialize sum to zero in the beginning because a value of zero indicates that it has not accumulated
anything. If we fail to initialize sum, the program will generate a run-time error when it attempts
to use the += operator to modify the (non-existent) variable. Within the loop we repeatedly add the
user’s input values to sum. When the loop finishes (because the user entered a negative number), sum
holds the sum of all the nonnegative values entered by the user.
The initialization of entry to zero coupled with the condition entry >= 0 of the while guarantees
that the program will execute the body of the while loop at least once. The if statement ensures that
the program will not add a negative entry to sum. (Could the if condition have used > instead of >= and
achieved the same results?) When the user enters a negative value, the executing program will not
update
the sum variable, and the condition of the while will no longer be true. The loop then terminates and the
Listing 5.4 (addnonnegatives.py) shows that a while loop can be used for more than simple counting.
The program does not keep track of the number of values entered. The program simply accumulates the
We can use a while statement to make Listing 4.14 (troubleshoot.py) more convenient for the user.
Recall that the computer troubleshooting program forces the user to rerun the program once a potential
program has been detected (for example, turn on the power switch, then run the program again to see
what
else might be wrong). A more desirable decision logic is shown in Figure 5.2.
Listing 5.5 (troubleshootloop.py) incorporates a while statement so that the program’s execution con-
tinues until the problem is resolved or its resolution is beyond the capabilities of the program.
print("Plug it in.")
else: # It is plugged in
print("Turn it on.")
print("necessary.")
A while block makes up the bulk of Listing 5.5 (troubleshootloop.py). The Boolean variable done
controls the loop; as long as done is false, the loop continues. A Boolean variable like done used in this
fashion is often called a flag. You can think of the flag being down when the value is false and raised
when
it is true. In this case, when the flag is raised, it is a signal that the loop should terminate.
not done
of the while statement’s condition evaluates to the opposite truth value of the variable done; the
expression
does not affect the value of done. In other words, the not operator applied to a variable does not modify
the variable’s value. In order to actually change the variable done, you would need to reassign it, as in
For Listing 5.5 (troubleshootloop.py) we have no need to invert done’s value. We ensure that done’s
value
is False initially and then make it True when the user has exhausted the program’s options.
statement. Python interprets the integer value 0 and floating-point value 0.0 both as False. All other
integer
and floating-point values, both positive and negative, are considered True. This means the following
code:
x -= 1 # Decrement x
is equivalent to
while x != 0:
x -= 1 # Decrement x
Speaking of floating-point values, Section 3.1 demonstrated how the limited precision of floating-point
numbers can be a problem. You should use caution when using a floating-point number to control a
loop,
x = 0.0
while x != 1.0:
print(x)
x += 0.1
print("Done")
The programmer’s intention is for Listing 5.6 (stopatone.py) to begin at 0.0 and count up to 1.0 by
tenths.
In other words, the program should stop looping when the variable x becomes 1.0. With true
mathematical
10
0.0
0.1
0.2
0.30000000000000004
0.4
0.5
0.6
0.7
0.7999999999999999
0.8999999999999999
0.9999999999999999
1.0999999999999999
1.2
1.3
1.4000000000000001
1.5000000000000002
10
x += 0.1
to be
x += 0.125
representation. Since such exact representations of floating-point values are rare, you should avoid
using
the == and != operators with floating-point numbers to control the number of loop iterations. Listing 5.7
(stopatonefixed.py) uses <= to control the loop instead of !=, and it behaves as expected.
x = 0.0
while x != 1.0:
print(x)
x += 0.1
print("Done")
In Listing 5.8 (definite1.py), code similar to Listing 5.1 (counttofive.py), prints the integers from one to
10.
n=1
print(n)
n += 1
We can inspect the code and determine the exact number of iterations the loop will perform. This kind
of
loop is known as a definite loop, since we can predict exactly how many times the loop repeats.
Consider
n=1
stop = int(input())
print(n)
n += 1
Looking at the source code of Listing 5.9 (definite2.py), we cannot predict how many times the loop will
repeat. The number of iterations depends on the input provided by the user. However, at the program’s
point
of execution after obtaining the user’s input and before the start of the execution of the loop, we would
be
able to determine the number of iterations the while loop would perform. Because of this, the loop in
else:
In Listing 5.10 (indefinite.py), we cannot predict at any point during the loop’s execution how many
itera-
tions the loop will perform. The value to match (999) is know before and during the loop, but the
variable
entry can be anything the user enters. The user could choose to enter 0 exclusively or enter 999 immedi-
ately and be done with it. The while statement in Listing 5.10 (indefinite.py) is an example of an
indefinite
loop.
The while statement is ideal for indefinite loops. Although we have used the while statement to
implement definite loops, Python provides a better alternative for definite loops: the for statement.
The while loop is ideal for indefinite loops. As Listing 5.5 (troubleshootloop.py) demonstrated, a
program-
mer cannot always predict how many times a while loop will execute. We have used a while loop to
n=1
print(n)
n += 1
The print statement in this code executes exactly 10 times every time this code runs. This code requires
• initialization: n = 1
• check: n <= 10
• update: n += 1
Python provides a more convenient way to express a definite loop. The for statement iterates over a
sequence of values. One way to express a sequence is via a tuple, as shown here:
for n in 1, 2, 3, 4, 5, 6, 7, 8, 9, 10:
print(n)
This code behaves identically to the while loop above. The print statement here executes exactly 10
times.
The code first prints 1, then 2, then 3, etc. The final value it prints is 10. During the iteration the variable
n
thus assumes, in order, all the values that make up the tuple.
It usually is cumbersome to explicitly list all the elements of a tuple, and often it is impractical. Consider
iterating over all the integers from 1 to 1,000—writing out all the tuple’s elements would be unwieldy.
Fortunately, Python provides a convenient way to express a sequence of integers that follow a regular
pattern. The following code uses a range expression to print the integers 1 through 10:
print(n)
The expression range(1, 11) creates a range object that allows the for loop to assign to the variable n
the values 1, 2, . . . , 10. Conceptually, the expression range(1, 11) represents the sequence of integers
1,2,3,4,5,6,7,8,9,10.
The line
is best read as “For each integer n in the range 1 ≤ n < 11.” During the first iteration of the loop, n’s value
is 1 within the block. In the loop’s second iteration, n has the value of 2. Each time through the loop, n’s
value increases by one. The code within the block will use the values of n up to 10.
range( begin,end,step )
where
• begin is the first value in the range; if omitted, the default value is 0
• end is one past the last value in the range; the end value is always required and may not be omitted
• step is the amount to increment or decrement; if the step parameter is omitted, it defaults to 1
(counts
up by ones)
begin, end, and step must all be integer expressions; floating-point expressions and other types are not
allowed. The arguments in the range expression may be literal numbers (like 10), variables (like x, if x is
The range expression is very flexible. Consider the following loop that counts down from 21 to 3 by
threes:
It prints
21 18 15 12 9 6 3
The following code computes and prints the sum of all the positive integers less than 100:
sum += i
print(sum)
The following examples show how to use range to produce a variety of sequences:
• range(10) → 0,1,2,3,4,5,6,7,8,9
• range(-5, 5) → −5,−4,−3,−2,−1,0,1,2,3,4
• range(1, 2) → 1
• range(1, 1) → (empty)
• range(0) → (empty)
In a range expression with one argument, as in range(x), the x represents the end of the range, with 0
being the implied begin value, and 1 being the step value.
In a range expression with two arguments, as in range(x, y), the x represents the begin value, and y
In a range expression with three arguments, as in range(x, y, z), the x represents the begin value, y
Loops allow us to rewrite an expanded form of Listing 2.20 (powers10right.py) more compactly. List-
ing 5.11 (powers10loop.py) uses a for loop to print the first 16 powers of 10.
for i in range(16):
01
1 10
2 100
3 1000
4 10000
5 100000
6 1000000
7 10000000
8 100000000
9 1000000000
10 10000000000
11 100000000000
12 1000000000000
13 10000000000000
14 100000000000000
15 1000000000000000
In a for loop the range object has complete control over determining the loop variable each time
through the loop. To prove this, Listing 5.12 (abusefor.py) attempts to thwart the range’s loop variable
by
for i in range(10):
if i == 5:
print()
0 (0) 1 (1) 2 (2) 3 (3) 4 (4) 5 (20) 6 (6) 7 (7) 8 (8) 9 (9)
The first number is i’s value at the beginning of the block, and the parenthesized number is i’s value at
the end of the block before the next iteration. The code within the block can reassign i, but this binds i
to
a different integer object (20). The next time through the loop the for statement obtains the next
integer
If you look in older Python books or at online examples of Python code, you prob-
ably will encounter the xrange expression. Python 2 has both range and xrange,
but Python 3 (the version we use in this text) does not have the xrange expres-
a list, and this process can involve considerable overhead for an executing pro-
gram. The xrange expression in Python 2 avoids this overhead, making it more
efficient than range, especially for a large sequence. When building loops with
the for statement, Python 2 programmers usually use xrange rather than range
to improve their code’s efficiency. In Python 3, we can use range without com-
list out of a Python 3 range expression, so Python 3 does not need two different
We initially emphasize the for loop’s ability to iterate over integer sequences because this is a useful
and common task in software construction. The for loop, however, can iterate over any iterable object.
As we have seen, a tuple is an iterable object, and a range object is an iterable object. A string also is an
iterable object. We can use a for loop to iterate over the characters that comprise a string. Listing 5.13
print(letter)
In the following sample execution of Listing 5.13 (stringletters.py) shows how the program responds
when
At each iteration of its for loop Listing 5.13 (stringletters.py) assigns to the letter variable a string con-
Listing 5.14 (stringliteralletters.py) uses a for loop to iterate over a literal string.
for c in 'ABCDEF':
print()
[A][B][C][D][E][F]
Listing 5.15 (countvowels.py) counts the number of vowels in the text provided by the user.
for c in word:
Listing 5.14 (stringliteralletters.py) prints vowels it finds and then reports how many it found:
a, a, a, i, e, a, (6 vowels)
Chapter 10 and beyond use the for statement to traverse data structures such as lists and dictionaries.
Just like with if statements, while and for blocks can contain arbitrary Python statements, including
other loops. A loop can therefore be nested within another loop. To see how nested loops work,
consider a
program that prints out a multiplication table. Elementary school students use multiplication tables, or
times
tables, as they learn the products of integers up to 10 or even 12. Figure 5.3 shows a 10 × 10
multiplication
table. We want our multiplication table program to be flexible and allow the user to specify the table’s
size. We will begin our development work with a simple program and add features as we go. First, we
will
not worry about printing the table’s row and column titles, nor will we print the lines separating the
titles
from the contents of the table. Initially we will print only the contents of the table. We will see we need
a
nested loop to print the table’s contents, but that still is too much to manage in our first attempt. In our
first
attempt we will print the rows of the table in a very rudimentary manner. Once we are satisfied that our
simple program works we can add more features. Listing 5.16 (timestable1.py) shows our first attempt
at a
muliplication table.
Listing 5.16: timestable1.py
Row #1
Row #2
Row #3
Row #4
Row #5
Row #6
Row #7
Row #8
Row #9
Row #10
Listing 5.16 (timestable1.py) does indeed print each row in its proper place—it just does not supply the
needed detail for each row. Our next step is to refine the way the program prints each row. Each row
should
contain size numbers. Each number within each row represents the product of the current row and
current
column; for example, the number in row 2, column 5 should be 2 × 5 = 10. In each row, therefore,
we must vary the column number from from 1 to size. Listing 5.17 (timestable2.py) contains the needed
refinement.
We use a loop to print the contents of each row. The outer loop controls how many total rows the
program
prints, and the inner loop, executed in its entirety each time the program prints a row, prints the
individual
1 2 3 4 5 6 7 8 9 10
2 4 6 8 10 12 14 16 18 20
3 6 9 12 15 18 21 24 27 30
4 8 12 16 20 24 28 32 36 40
5 10 15 20 25 30 35 40 45 50
6 12 18 24 30 36 42 48 54 60
7 14 21 28 35 42 49 56 63 70
8 16 24 32 40 48 56 64 72 80
9 18 27 36 45 54 63 72 81 90
10 20 30 40 50 60 70 80 90 100
The numbers within each column are not lined up nicely, but the numbers are in their correct positions
relative to each other. We can use the string formatter introduced in Listing 2.20 (powers10right.py) to
right justify the numbers within a four-digit area. Listing 5.18 (timestable3.py) contains this alignment
adjustment.
1 2 3 4 5 6 7 8 9 10
2 4 6 8 10 12 14 16 18 20
3 6 9 12 15 18 21 24 27 30
4 8 12 16 20 24 28 32 36 40
5 10 15 20 25 30 35 40 45 50
6 12 18 24 30 36 42 48 54 60
7 14 21 28 35 42 49 56 63 70
8 16 24 32 40 48 56 64 72 80
9 18 27 36 45 54 63 72 81 90
10 20 30 40 50 60 70 80 90 100
12345
2 4 6 8 10
3 6 9 12 15
4 8 12 16 20
5 10 15 20 25
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
2 4 6 8 10 12 14 16 18 20 22 24 26 28 30
3 6 9 12 15 18 21 24 27 30 33 36 39 42 45
4 8 12 16 20 24 28 32 36 40 44 48 52 56 60
5 10 15 20 25 30 35 40 45 50 55 60 65 70 75
6 12 18 24 30 36 42 48 54 60 66 72 78 84 90
7 14 21 28 35 42 49 56 63 70 77 84 91 98 105
All that is left is to add the row and column titles and the lines that bound the edges of the table.
When the user supplies the value 10, Listing 5.19 (timestable4.py) produces
1 2 3 4 5 6 7 8 9 10
+----------------------------------------
1 | 1 2 3 4 5 6 7 8 9 10
2 | 2 4 6 8 10 12 14 16 18 20
3 | 3 6 9 12 15 18 21 24 27 30
4 | 4 8 12 16 20 24 28 32 36 40
5 | 5 10 15 20 25 30 35 40 45 50
6 | 6 12 18 24 30 36 42 48 54 60
7 | 7 14 21 28 35 42 49 56 63 70
8 | 8 16 24 32 40 48 56 64 72 80
9 | 9 18 27 36 45 54 63 72 81 90
10 | 10 20 30 40 50 60 70 80 90 100
An input of 15 yields
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+------------------------------------------------------------
1 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
2 | 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30
3 | 3 6 9 12 15 18 21 24 27 30 33 36 39 42 45
4 | 4 8 12 16 20 24 28 32 36 40 44 48 52 56 60
5 | 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75
6 | 6 12 18 24 30 36 42 48 54 60 66 72 78 84 90
7 | 7 14 21 28 35 42 49 56 63 70 77 84 91 98 105
1234567
+----------------------------
1|1234567
2 | 2 4 6 8 10 12 14
3 | 3 6 9 12 15 18 21
4 | 4 8 12 16 20 24 28
5 | 5 10 15 20 25 30 35
6 | 6 12 18 24 30 36 42
7 | 7 14 21 28 35 42 49
+----
1|1
As we can see, the table automatically adjusts to the size and spacing required by the user’s input.
• It is important to distinguish what is done only once (outside all loops) from that which is done
repeatedly. The column heading across the top of the table is outside of all the loops; therefore, the
• The work to print the heading for the rows is distributed throughout the execution of the outer loop.
This is because the heading for a given row cannot be printed until all the results for the previous row
right justifies the value of product in field that is four characters wide. This technique properly aligns
the columns within the times table.
• In the nested loop, row is the control variable for the outer loop; column controls the inner loop.
• The inner loop executes size times on every single iteration of the outer loop. This means the
innermost statement
executes size × size times, one time for every product in the table.
• The program prints a newline after it displays the contents of each row; thus, all the values printed in
Nested loops are necessary when an iterative process itself must be repeated. In our times table
example,
a for loop prints the contents of each row, and an enclosing for loop prints out each row.
Listing 5.20 (permuteabc.py) uses a triply-nested loop to print all the different arrangements of the
letters A, B, and C. Each string printed is a permutation of ABC. A permutation, therefore, is a possible
ordering of a sequence.
# File permuteabc.py
Notice how the if statements prevent duplicate letters within a given string. The output of Listing 5.20
ABC
ACB
BAC
BCA
CAB
CBA
Listing 5.21 (permuteabcd.py) uses a four-deep nested loop to print all the different arrangements of
the
# File permuteabcd.py
Nested loops are powerful, and some novice programmers attempt to use nested loops where a single
loop is more appropriate. Before you attempt to solve a problem with a nested loop, make sure that
there is
no way you can do so with a single loop. Nested loops are more difficult to write correctly and, when not
Normally, a while statement executes until its condition becomes false. A running program checks this
condition first to determine if it should execute the statements in the loop’s body. It then re-checks this
condition only after executing all the statements in the loop’s body. Ordinarily a while loop will not
immediately exit its body if its condition becomes false before completing all the statements in its body.
The
while statement is designed this way because usually the programmer intends to execute all the
statements
within the body as an indivisible unit. Sometimes, however, it is desirable to immediately exit the body
or
recheck the condition from the middle of the loop instead. Said another way, a while statement checks
its
condition only at the “top” of the loop. It is not the case that a while loop finishes immediately
whenever
its condition becomes true. Listing 5.22 (whileexitattop.py) demonstrates this top-exit behavior.
x = 10
while x == 10:
Even though the condition for continuing in the loop (x being equal to 10) changes in the middle of the
loop’s body, the while statement does not check the condition until it completes all the statements in its
Sometimes it is more convenient to exit a loop from the middle of its body; that is, quit the loop before
all the statements in its body execute. This means if a certain condition becomes true in the loop’s body,
Similarly, a for statement typically iterates over all the values in its range or over all the characters in
its string. Sometimes, however, it is desirable to exit the for loop prematurely. Python provides the
break
and continue statements to give programmers more flexibility designing the control logic of loops.
As we noted above, sometimes it is necessary to exit a loop from the middle of its body; that is, quit the
loop before all the statements in its body execute. This means if a certain condition becomes true in the
loop’s body, exit right away. This “middle-exiting” condition could be the same condition that controls
the
while loop (that is, the “top-exiting” condition), but it does not need to be.
Python provides the break statement to implement middle-exiting loop control logic. The break
statement causes the program’s execution to immediately exit from the body of the loop. Listing 5.23
(addmiddleexit.py) is a variation of Listing 5.4 (addnonnegatives.py) that illustrates the use of break.
The condition of the while statement in Listing 5.23 (addmiddleexit.py) is a tautology, so when the
program
runs it is guaranteed to begin executing the statements in its while block at least once. Since the
condition
of the while can never be false, the break statement is the only way to get out of the loop. Here, the
break
statement executes only when it determines that the number the user entered is negative. When the
program
encounters the break statement during its execution, it skips any statements that follow in the loop’s
body
and exits the loop immediately. The keyword break means “break out of the loop.” The placement of
the
break statement in Listing 5.23 (addmiddleexit.py) makes it impossible to add a negative number to the
sum
variable.
Listing 5.5 (troubleshootloop.py) uses a variable named done that controls the duration of the loop.
Listing 5.24 (troubleshootloop2.py) uses break statements in place of the Boolean done variable.
while True:
print("Plug it in.")
else: # It is plugged in
print("Turn it on.")
print("necessary.")
Some software designers believe that programmers should use the break statement sparingly because
it deviates from the normal loop control logic. Ideally, every loop should have a single entry point and
single exit point. While Listing 5.23 (addmiddleexit.py) has a single exit point (the break statement),
some programmers commonly use break statements within while statements in the which the condition
for the while is not a tautology. Adding a break statement to such a loop adds an extra exit point (the
top of the loop where the condition is checked is one point, and the break statement is another). Most
programmers find two exits point perfectly acceptable, but much above two break points within a single
The break statement is not absolutely required for full control over a while loop; that is, we can rewrite
any Python program that contains a break statement within a while loop so that it behaves the same
way but
Figure 5.4 The code on the left generically represents any while loop that uses a break statement. The
code on the right shows how we can transform the loop into a functionally equivalent form that does
not
use break.
Eliminate
the
break
statement
looping = True
if :
looping = False
else:
Condition 1
Part A
Condition 2
Part B
Part C
Condition 1
Condition 2
Part A
Part B
Part C
while :
if :
break
does not use a break. Figure 5.4 shows how we can transform any while loop that uses a break
statement
into a beak-free version. The no-break version introduces a Boolean variable (looping), and the loop
control logic is a little more complicated. The no-break version uses more memory (an extra variable)
and more time to execute (requires an extra check in the loop condition during every iteration of the
loop).
This extra memory is insignificant, and except for rare, specialized applications, the extra execution time
is
imperceptible. In most cases, the more important issue is that the more complicated the control logic
for
a given section of code, the more difficult the code is to write correctly. In some situations, even though
it
violates the “single entry point, single exit point” principle, a simple break statement is a desirable loop
control option.
We can use the break statement inside a for loop as well. Listing 5.25 (countvowelsnox.py) shows how
we can use a break statement to exit a for loop prematurely. provided by the user.
vowel_count = 0
for c in word:
break
If the program detects an X or x anywhere in the user’s input string, it immediately exits the for even
though
it may not have considered all the characters in the string. Consider the following sample run:
a, a, a, i, (4 vowels)
The program breaks out of the loop when it attempts to process the x in the user’s input.
The break statement is handy when a situation arises that requires immediate exit from a loop. The for
loop in Python behaves differently from the while loop, in that it has no explicit condition that it checks
to continue its iteration. We must use a break statement if we wish to prematurely exit a for loop before
it has completed its specified iterations. The for loop is a definite loop, which means programmers can
determine up front the number of iterations the loop will perform. The break statement has the
potential to
disrupt this predictability. For this reason, programmers use break statements in for loops less
frequently,
and they often serve as an escape from a bad situation that continued iteration might make worse.
When a program’s execution encounters a break statement inside a loop, it skips the rest of the body of
the
loop and exits the loop. The continue statement is similar to the break statement, except the continue
statement does not necessarily exit the loop. The continue statement skips the rest of the body of the
loop
and immediately checks the loop’s condition. If the loop’s condition remains true, the loop’s execution
resumes at the top of the loop. Listing 5.26 (continueexample.py) shows the continue statement in
action.
sum = 0
done = False
if val < 0:
if val != 999:
print("Tallying", val)
sum += val
else:
Programmers do not use the continue statement as frequently as the break statement since it is
very easy to transform the code that uses continue into an equivalent form that does not. Listing 5.27
(nocontinueexample.py) works exactly like Listing 5.26 (continueexample.py), but it avoids the continue
statement.
sum = 0
done = False
if val < 0:
else:
if val != 999:
Figure 5.5 The code on the left generically represents any loop that uses a continue statement. It is
possible to transform the code on the left to eliminate the continue statement, as the code on the right
shows.
Condition 1
Condition 2
Part A
Part B
Part C
while :
if :
continue
Eliminate
the
continue
statement
while :
if :
else:
Condition 1
Part A
Condition 2
Part B
Part C
print("Tallying", val)
sum += val
else:
that does not use continue. The transformation is simpler than for break elimination (see Figure 5.4)
since the loop’s condition remains the same, and no additional variable is needed. The logic of the else
version is no more complex than the continue version. Therefore, unlike the break statement above,
there
is no compelling reason to use the continue statement. Sometimes a programmer may add a continue
statement at the last minute to an existing loop body to handle an exceptional condition (like ignoring
negative numbers in the example above) that initially went unnoticed. If the body of the loop is lengthy,
the programmer can add a conditional statement with a continue near the top of the loop body without
touching the logic of the rest of the loop. The continue statement thus merely provides a convenient
Python loops support an optional else block. The else block in the context of a loop provides code to
execute when the loop exits normally. Said another way, the code in a loop’s else block does not
execute
When a while loop exits due to its condition being false during its normal check, its associated else
block executes. This is true even if its condition is found to be false before its body has had a chance to
execute. Listing 5.28 (whileelse.py) shows how the while/else statement works.
count = sum = 0
if val < 0:
break
count += 1
sum += val
else:
When the user behaves and supplies only nonnegative values to Listing 5.28 (whileelse.py), it computes
the
Enter number: 23
Enter number: 12
Enter number: 14
Enter number: 10
Enter number: 11
Average = 14.0
When the user does not comply with the instructions, the program will print a corrective message and
not
Enter number: 23
Enter number: 12
Enter number: -4
It may be more natural to read the else keyword for the while statement as “if no break,” meaning
execute
the code in the else block if the program’s execution of code in the while block did not encounter the
break
statement.
The else block is not essential; Listing 5.29 (whilenoelse.py) uses if/else statement to achieve the
count = sum = 0
if val < 0:
break
count += 1
sum += val
if count < 5:
else:
Listing 5.29 (whilenoelse.py) uses two distinct Python constructs, the while statement followed by an
if/else statement, whereas Listing 5.28 (whileelse.py) uses only one, a while/else statement. List-
ing 5.29 (whilenoelse.py) also must check the count < 5 condition twice, once in the while statement and
loop exits because it has considered all the values in its range or all the characters in its string, it
executes
the code in its associated else block. If a for/else statement exits prematurely due to a break statement,
it does not execute the code in its else block. Listing 5.30 (countvowelselse.py) shows how the else block
vowel_count = 0
for c in word:
break
else:
Unlike Listing 5.15 (countvowels.py), Listing 5.30 (countvowelselse.py), does not print the number of
vow-
An infinite loop is a loop that executes its block of statements repeatedly until the user forces the
program
to quit. Once the program flow enters the loop’s body it cannot escape. Infinite loops sometimes are by
design. For example, a long-running server application like a Web server may need to continuously
check
for incoming connections. The Web server can perform this checking within a loop that runs indefinitely.
Beginning programmers, unfortunately, all too often create infinite loops by accident, and these infinite
while True:
# Do something forever. . .
The Boolean literal True is always true, so it is impossible for the loop’s condition to be false. The only
ways to exit the loop is via a break statement, return statement (see Chapter 7), or a sys.exit call (see
Intentional infinite loops are easy to write correctly. Accidental infinite loops are quite common, but
can be puzzling for beginning programmers to diagnose and repair. Consider Listing 5.31 (findfactors.py)
that attempts to print all the integers with their associated factors from 1 to 20.
MAX = 20 # MAX is 20
n = 1 # Start with 1
n += 1
It displays
1: 1
2: 1 2
3: 1
and then ”freezes up” or ”hangs,” ignoring any user input (except the key sequence Ctrl C on most
systems which interrupts and terminates the running program). This type of behavior is a frequent
symptom
of an unintentional infinite loop. The factors of 1 display properly, as do the factors of 2. The program
displays the first factor of 3 properly and then hangs. Since the program is short, the problem may be
easy to locate. In some programs, though, the error may be challenging to find. Even in Listing 5.31
(findfactors.py) the debugging task is nontrivial since the program involves nested loops. (Can you find
and
In order to avoid infinite loops, we must ensure that the loop exhibits certain properties:
• The loop’s condition must not be a tautology (a Boolean expression that can never be false). For
would produce an infinite loop since any value chosen for i will satisfy one or both of the two
subconditions. Perhaps the programmer intended to use and instead of or to stay in the loop as long
n <= MAX
If n is 21 and MAX is 20, then the condition is false. Since we can find values for n and MAX that make
this expression false, it cannot be a tautology. Checking the inner loop condition:
factor <= n
we see that if factor is 3 and n is 2, then the expression is false; therefore, this expression also is not
a tautology.
• The condition of a while must be true initially to gain access to its body. The code within the body
must modify the state of the program in some way so as to influence the outcome of the condition that
is checked at each iteration. This usually means the body must be able to modify one of the variables
used in the condition. Eventually the variable assumes a value that makes the condition false, and the
loop terminates.
In Listing 5.31 (findfactors.py) the outer loop’s condition involves the variables n and MAX. We observe
that we assign 20 to MAX before the loop and never change it afterward, so to avoid an infinite loop it
is essential that n be modified within the loop. Fortunately, the last statement in the body of the outer
loop increments n. n is initially 1 and MAX is 20, so unless the circumstances arise to make the inner
The inner loop’s condition involves the variables n and factor. No statement in the inner loop
modifies n, so it is imperative that factor be modified in the loop. The good news is factor is
incremented in the body of the inner loop, but the bad news is the increment operation is protected
within the body of the if statement. The inner loop contains one statement, the if statement. That
if n % factor == 0:
factor += 1
If the condition of the if is ever false, the variable factor will not change. In this situation if the
expression factor <= n was true, it will remain true. This effectively creates an infinite loop. The
statement that modifies factor must be moved outside of the if statement’s body:
if n % factor == 0:
factor += 1
1: 1
2: 1 2
3: 1 3
4: 1 2 4
5: 1 5
6: 1 2 3 6
7: 1 7
8: 1 2 4 8
9: 1 3 9
10: 1 2 5 10
11: 1 11
12: 1 2 3 4 6 12
13: 1 13
14: 1 2 7 14
15: 1 3 5 15
16: 1 2 4 8 16
17: 1 17
18: 1 2 3 6 9 18
19: 1 19
20: 1 2 4 5 10 20
We can use a debugger can be used to step through a program to see where and why an infinite loop
arises. Another common technique is to put print statements in strategic places to examine the values of
the
variables involved in the loop’s control. We can augment the original inner loop in this way:
1: factor = 1 n = 1
2: factor = 1 n = 2
1 factor = 2 n = 2
3: factor = 1 n = 3
1 factor = 2 n = 3
factor = 2 n = 3
factor = 2 n = 3
factor = 2 n = 3
factor = 2 n = 3
factor = 2 n = 3
The program continues to print the same line until the user interrupts its execution. The output
demonstrates
that once factor becomes equal to 2 and n becomes equal to 3 the program’s execution becomes
trapped
It is imperative that the program increment factor each time through the inner loop; therefore, the
state-
ment incrementing factor must be moved outside of the if’s guarded body. Moving it outside means
removing it from the if statement’s block, which means unindenting it.
Listing 5.32 (findfactorsfor.py) is a different version of our factor finder program that uses nested for
loops instead of nested while loops. Not only is it slightly shorter, but it avoids the potential for the
misplaced increment of the factor variable. This is because the for statement automatically handles the
MAX = 20 # MAX is 20
As a final note on infinite loops, Section 1.4 mentioned the preference for using the Debug option under
the WingIDE-101 integrated development environment when running our programs. When executing
the
program under the Run option, the IDE can become unresponsive if the program encounters an infinite
loop.
At that point, terminating the IDE is the only solution. Under the debugger, we very easily can interrupt
a
We can implement some sophisticated algorithms in Python now that we are armed with if and while
statements. This section provides several examples that show off the power of conditional execution
and
iteration.
Suppose you must write a Python program that computes the square root of a number supplied by the
user.
We can compute the square root of a number by using the following simple strategy:
2. Square the guess and see how close it is to the original number; if it is close enough to the correct
answer, stop.
3. Make a new guess that will produce a better result and proceed with step 2.
Step 3 is a little vague, but Listing 5.33 (computesquareroot.py) implements the above strategy in
Python,
# File computesquareroot.py
root = 1.0
The program is based on a simple algorithm that uses successive approximations to zero in on an answer
The following shows the program’s output when the user enters the value 2:
Enter number: 2
The actual square root is approximately 1.4142135623730951 and so the result is within our accepted
The real answer, of course, is 10, but our computed result again is well within our programmed
tolerance.
While Listing 5.33 (computesquareroot.py) is a good example of the practical use of a loop, if we really
need to compute the square root, Python has a library function that is more accurate and more efficient.
We
Suppose we wish to draw a triangular tree with its height provided by the user. A tree that is five levels
tall
***
*****
*******
*********
***
*****
If the height of the tree is fixed, we can write the program as a simple variation of Listing 1.2 (arrow.py)
which uses only printing statements and no loops. Our program, however, must vary its height and
width
row = 0
count = 0
print(end=' ')
count += 1
count = 0
print(end='*')
count += 1
print()
The following shows a sample run of Listing 5.34 (startree.py) where the user enters 7:
***
*****
*******
*********
***********
*************
Listing 5.34 (startree.py) uses two sequential while loops nested within a while loop. The outer while
loop draws one row of the tree each time its body executes:
• As long as the user enters a value greater than zero, the body of the outer while loop will execute; if
the user enters zero or less, the program terminates and does nothing. This is the expected behavior.
row += 1
ensures that the variable row increases by one each time through the loop; therefore, it eventually
will equal height (since it initially had to be less than height to enter the loop), and the loop will
• The first inner loop prints spaces. The number of spaces it prints is equal to the height of the tree the
first time through the outer loop and decreases each iteration. This is the correct behavior since each
succeeding row moving down contains fewer leading spaces but more asterisks.
• The second inner loop prints the row of asterisks that make up the tree. The first time through the
outer
loop, row is zero, so it prints no left side asterisks, one central asterisk, and no right side asterisks.
Each time through the loop the number of left-hand and right-hand stars to print both increase by
one, but there remains just one central asterisk to print. This means the tree grows one wider on each
side for each line moving down. Observe how the 2*row + 1 value expresses the needed number of
asterisks perfectly.
• While it seems asymmetrical, note that no third inner loop is required to print trailing spaces on the
line after the asterisks are printed. The spaces would be invisible, so there is no reason to print them!
For comparison, Listing 5.35 (startreefor.py) uses for loops instead of while loops to draw our star
trees. The for loop is a better choice for this program since once the user provides the height, the
program
can calculate exactly the number of iterations required for each loop. This number will not change
during
the rest of the program’s execution, so the definite loop (for) is better a better choice than the indefinite
loop (while).
print(end=' ')
print(end='*')
print()
A prime number is an integer greater than one whose only factors (also called divisors) are one and
itself.
For example, 29 is a prime number (only 1 and 29 divide into 29 with no remainder), but 28 is not (1, 2,
4,
7, and 14 are factors of 28). Prime numbers were once merely an intellectual curiosity of
mathematicians,
but now they play an important role in cryptography and computer security.
The task is to write a program that displays all the prime numbers up to a value entered by the user.
Listing 5.36 (printprimes.py) provides one solution.
trial_factor = 2
if value % trial_factor == 0:
if is_prime:
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89
The logic of Listing 5.36 (printprimes.py) is a little more complex than that of Listing 5.34 (startree.py).
The user provides a value for max_value. The main loop (outer while) iterates over all the values from
two
to max_value:
• The program initializes the is_prime variable to true, meaning it assumes value is a prime number
unless later tests prove otherwise. trial_factor takes on all the values from two to value - 1 in
trial_factor = 2
if value % trial_factor == 0:
The expression value % trial_factor is zero when trial_factor divides into value with no
trial_factor that actually is a factor of value, then it sets is_prime false and exits the loop via
the break statement. If the loop continues to completion, the program will not set is_prime to false,
if is_prime:
simply checks the status of is_prime. If is_prime is true, then value must be prime, so the pro-
gram prints value followed by a space to separate it from other factors that it may print during the
remaining iterations.
is true, since 2 ≤ 2. The executing program sets is_prime to true, but the condition of the inner loop
trial_factor < value
is not true (2 is not less than 2). Thus, the program skips the inner loop, it does not change is_prime
from true, and so it prints 2. This behavior is correct because 2 is the smallest prime number (and the
2. If the user enters a number less than 2, what will the program print?
The while condition ensures that values less than two are not considered. The program will never
enter the body of the while. The program prints only the newline, and it displays no numbers. This
In order to enter the body of the inner loop, trial_factor must be less than value. value does not
change anywhere in the loop. trial_factor is not modified anywhere in the if statement within
the loop, and it is incremented within the loop immediately after the if statement. trial_factor
is, therefore, incremented during each iteration of the loop. Eventually, trial_factor will equal
In order to enter the body of the outer loop, value must be less than or equal to max_value.
max_value does not change anywhere in the loop. The last statement within the body of the outer
loop increases value, and no where else does the program modify value. Since the inner loop is
guaranteed to terminate as shown in the previous answer, eventually value will exceed max_value
We can rearrange slightly the logic of the inner while to avoid the break statement. The current version
is:
if value % trial_factor == 0:
This version without the break introduces a slightly more complicated condition for the while but
removes
the if statement within its body. is_prime is initialized to true before the loop. Each time through the
loop
it is reassigned. trial_factor will become false if at any time value % trial_factor is zero. This is
exactly when trial_factor is a factor of value. If is_prime becomes false, the loop cannot continue, and
if is_prime never becomes false, the loop ends when trial_factor becomes equal to value. Because of
are not necessary. The parentheses do improve readability, since an expression including both = and !=
is
awkward for humans to parse. When parentheses are placed where they are not needed, as in
x = (y + 2)
the interpreter simply ignores them, so there is no efficiency penalty in the executing program.
We can shorten the code of Listing 5.36 (printprimes.py) a bit by using for statements instead of while
if value % trial_factor == 0:
is_prime = False # Found a factor
if is_prime:
We can simplify Listing 5.37 (printprimesfor.py) even further by using the for/else statement as List-
if value % trial_factor == 0:
else:
If the inner for loop completes its iteration over all the values in its range, it will execute the print
statement
in its else block. The only way the inner for loop can be interrupted is if it discovers a factor of value. If
it does find a factor, the premature exit of the inner for loop prevents the execution of its else block.
This
Listing 5.39 (betterinputonly.py) traps the user in a loop until the user provides an acceptable integer
value.
attempts += 1
We initialize the variable in_value at the top of the program only to make sure the loop’s body executes
at
least one time. A definite loop (for) is inappropriate for a program like Listing 5.39 (betterinputonly.py)
be-
cause the program cannot determine ahead of time how many attempts the user will make before
providing
a value in range.
5.9 Exercises
1. In Listing 5.4 (addnonnegatives.py) could the condition of the if statement have used > instead of
2. In Listing 5.4 (addnonnegatives.py) could the condition of the while statement have used > instead
were moved out of the loop? Is moving the assignment out of the loop a good or bad thing to do?
Why?
a=0
print('*', end='')
a += 1
print()
a=0
print('*', end='')
print()
a=0
a += 1
print()
a=0
b=0
print('*', end='')
b += 1
print()
a += 1
a=0
if a % 5 == 0:
print('*', end='')
a += 1
print()
a=0
b=0
if (a + b) % 2 == 0:
print('*', end='')
b += 1
print()
a += 1
10. How many asterisks does the following code fragment print?
a=0
b=0
c=0
print('*', end='')
c += 1
b += 1
a += 1
print()
13. Provide the exact sequence of integers specified by each of the following range expressions.
(a) range(5)
(f) range(10, 5)
(g) range(0)
15. Provide an equivalent Python range expression for each of the following integer sequences.
(a) 1,2,3,4,5
(b) 5,4,3,2,1
(c) 5,10,15,20,25,30
(d) 30,25,20,15,10,5
(e) −3,−2,−1,0,1,2,3
(f) 3,2,1,0,−1,−2,−3
(g) −50,−40,−30,−20,−10
16. If x is bound to the integer value 2, what integer sequence does range(x, 10*x, x) represent?
17. If x is bound to the integer value 2 and y is bound to the integer 5, what integer sequence does
range(x, x + y) represent?
18. Is it possible to represent the following sequence with a Python range expression:
1,−1,2,−2,3,−3,4,−4?
19. How many asterisks does the following code fragment print?
for a in range(100):
print('*', end='')
print()
20. How many asterisks does the following code fragment print?
print('*', end='')
print()
21. How many asterisks does the following code fragment print?
for a in range(100, 0, -2):
print('*', end='')
print()
22. How many asterisks does the following code fragment print?
print('*', end='')
print()
23. How many asterisks does the following code fragment print?
print('*', end='')
print()
24. How many asterisks does the following code fragment print?
print('*', end='')
print()
25. Rewrite the code in the previous question so it uses a while instead of a for. Your code should
behave identically.
a=0
print(a)
a += 1
print()
27. Rewrite the code in the previous question so it uses a for instead of a while. Your code should
behave identically.
print(a)
a += 1
print()
29. Rewrite the following code fragment using a break statement and eliminating the done variable.
done = False
n, m = 0, 100
n = int(input())
if n < 0:
done = True
print("n =", n)
30. Rewrite the following code fragment so it eliminates the continue statement. Your new code’s logic
x=5
while x > 0:
y = int(input())
if y == 25:
continue
x -= 1
print('x =', x)
a=0
print()
32. Modify Listing 5.19 (timestable4.py) so that the it requests a number from the user. It should then
print a multiplication table of the size entered by the user; for example, if the users enters 15, a 15×15
table should be printed. Print nothing if the user enters a value lager than 18. Be sure everything lines
33. Write a Python program that accepts a single integer value entered by the user. If the value entered
is
less than one, the program prints nothing. If the user enters a positive integer, n, the program prints
an n×n box drawn with * characters. If the users enters 1, for example, the program prints
**
**
***
***
***
*******
*******
*******
*******
*******
*******
*******
34. Write a Python program that allows the user to enter exactly twenty floating-point values. The pro-
gram then prints the sum, average (arithmetic mean), maximum, and minimum of the values entered.
35. Write a Python program that allows the user to enter any number of nonnegative floating-point
values.
The user terminates the input list with any negative value. The program then prints the sum, average
(arithmetic mean), maximum, and minimum of the values entered. The terminating negative value is
36. Redesign Listing 5.34 (startree.py) so that it draws a sideways tree pointing right; for example, if the
**
***
****
*****
******
*******
******
*****
****
***
**
37. Redesign Listing 5.34 (startree.py) so that it draws a sideways tree pointing left; for example, if the
*
**
***
****
*****
******
*******
******
*****
****
***
**