Why this matters
A loop is a part of a program that repeats the same steps while a condition is true. A program that adds up a list of 1000 prices does not need 1000 separate lines of code. It needs one loop that runs 1000 times, once for each price.
Loops are where most beginners get stuck. The steps inside a loop are easy to read. The hard part is knowing when the loop stops, how many times it runs, and what the values look like on each pass. A flowchart makes those questions visible, because the arrow that goes back to the top of the loop is drawn in plain sight.
This lesson covers three loop shapes: a counter loop, which stops after a set number of passes, a sentinel loop, which stops when it sees a special marker value, and a loop with a break, which leaves the loop early when an answer is found. The flowchart symbols used here are the box, the diamond and the arrow. The rules for those symbols are in the earlier lesson on flowchart symbols, so they are not repeated here. The lesson on pseudocode for input validation covers checks on values that come from the user.
The shape of a loop
Every loop has three parts, and the flowchart shows each one.
The first part is the setup, the steps before the loop begins. A setup box gives the starting values, such as a total of 0 and a count of 0.
The second part is the test, a diamond with a question inside it, such as count < 3 ?. The answer is yes or no. A yes sends the flow into the body of the loop. A no sends the flow out of the loop, to whatever comes next.
The third part is the body, the boxes that do the repeated work. The body always ends with an arrow that goes back up to the test. That return arrow is what makes the shape a loop. Without it, the flow would go down once and never repeat.
Here is the shape in its plainest form. The arrows show the order of the steps.
start
|
v
set up starting values
|
v
+--> test: keep going? --no--> leave the loop --> end
| |
| yes
| v
| body: do the repeated work
| |
+--------+ the return arrow goes back to the testRead the flow with your finger. Start at the top, move down to the test, follow the yes arrow into the body, then follow the return arrow back up to the test. Check the test again. The loop only ends when the test gives a no.
Worked example 1: the counter loop
A counter loop keeps a number called a counter. The counter starts at 0, goes up by one on each pass, and the test checks whether the counter has reached a limit. This is the right shape when you know ahead of time how many times to repeat.
Take this problem. A student has three test scores, 72, 85 and 90. Add them up.
The values are stored in a list, which is an ordered set of values with positions. The first position is 0, the second is 1 and the third is 2. A list position is called an index. The loop uses the counter as the index, so on each pass it reads one score.
First, plan the chart with real values, because a loop is easier to check when you know what the numbers should be. The starting values are total = 0 and count = 0. The test is count < 3. The body adds scores[count] to total, then adds 1 to count.
Here is the flowchart.
start
|
v
set total = 0 and count = 0
|
v
+--> count < 3 ? --no--> print total --> end
| |
| yes
| v
| total = total + scores[count]
| count = count + 1
| |
+--------+Now the same loop as Python code. Python is a programming language that reads close to plain English, and it is used for every example in this lesson. The code uses while, which means repeat while the test is true.
The output is:
Counter loop: count = 3 total = 247The total is 247, which is 72 + 85 + 90. The count ends at 3, which is the length of the list.
A trace table is the next check. A trace table is a table that has one column for each variable and one row for each step, so you can write down the values as the program goes through them. Read the trace table as a record of the flowchart on paper. Each row is one trip around the arrow.
| Check | count | count < 3? | total after the body |
|---|---|---|---|
| Before the loop | 0 | 0 | |
| Pass 1 | 1 | yes | 72 |
| Pass 2 | 2 | yes | 157 |
| Pass 3 | 3 | yes | 247 |
| Test again | 3 | no | 247 |
The table shows the loop test run four times. Three of those checks said yes, and the fourth said no. That is the expected shape of a counter loop with three items. The last row is easy to forget, and it is the one that shows where the loop stops.
The counter must change
The body must move the counter. If the body did not add 1 to count, the test would always say yes, and the loop would never stop. The flowchart shows the problem clearly: the return arrow goes back to a test whose answer never changes. This is the most common loop mistake, and it is covered again in the mistakes section below.
Worked example 2: the sentinel loop
A sentinel is a special value that marks the end of a list. The sentinel is not real data. It is a signal. A common sentinel is -1 for a list of readings that are never negative, such as the number of cars that pass a counter each minute. The loop reads values one at a time, and it stops when the sentinel appears.
This shape is right when you do not know ahead of time how many values there are. The loop does not count. It asks, after each value, whether that value is the marker.
Take this problem. A sensor records readings, and the list ends with -1. Collect the readings before the -1, and do not include the -1 itself.
Here is the flowchart. Notice that the test comes first, and the value is read before the test.
start
|
v
position = 0, value = readings[position]
|
v
+--> value is -1 ? --yes--> print seen --> end
| |
| no
| v
| add value to seen
| position = position + 1, value = readings[position]
| |
+--------+The read happens twice: once before the loop, and once at the end of each pass. This is the usual pattern for a sentinel loop. The loop must have the next value ready before it tests it. If the next value is read only at the top of the loop, the first value is tested and then skipped.
Here is the sentinel loop in Python.
The output is:
Sentinel loop: seen = [12, 7, 30] stopped at position 3The loop stops at position 3, where the -1 sits. The value 99 after the sentinel is never read, because the loop stopped before it. That is the point of a sentinel: anything after it is ignored.
The list in this example has a -1. A real sensor would send values one at a time, and the program would ask the sensor for each value. The shape of the flowchart does not change. The box that reads the value is the only part that differs.
What the arrow means here
The return arrow goes back to the test, and the test is now a check on the newest value. When the value is -1, the yes arrow leaves the loop. When the value is anything else, the body runs and the flow comes back up to test the next value. The chart is the same shape as the counter loop, but the question at the diamond is different.
Worked example 3: leaving early with break
A break is a command that stops a loop at once, even when the test would still say yes. The flow goes straight to the first step after the loop. A break is the right tool when the loop has found what it was looking for, and the rest of the list does not matter.
Take this problem. A list holds five temperature readings in degrees. Find the position of the first reading above 35 degrees. If there is none, the answer is -1.
The loop will go through the list from the start. The first time it sees a reading above 35, it records the position and breaks. Without the break, the loop would keep going, and a later reading above 35 would overwrite the answer, so the program would report the last hot reading, not the first.
Here is the flowchart. The yes branch from the second diamond does not go back to the top. It goes straight to the printing box.
start
|
v
first_hot = -1, position = 0
|
v
+--> position < 5 ? --no--------------------------+
| | |
| yes |
| v |
| temperature[position] > 35 ? --yes--> first_hot = position
| | |
| no | break
| v |
| position = position + 1 |
| | |
+--------+ v
print first_hot --> endHere is the same loop in Python.
The output is:
Break: first hot reading at position 2The first hot reading is 38, at position 2. The loop stops there, so the 40 at position 4 is never checked. Had the break been left out, the loop would still give the position of 40 as the final value of first_hot_position, since 40 is also above 35. That difference is the reason for the break.
A for loop in Python is a counter loop with a built-in counter. range(len(temperatures)) produces the positions 0, 1, 2, 3 and 4, and the loop body runs once for each. The flowchart for this code has the same test and body as the counter loop, with a break added on one branch.
Where the break is needed
A break is useful when a search finds its answer early, and the search does not need to look at the rest. It is not needed when the loop must visit every item anyway, such as when adding up a total. Adding a break to a loop that must finish is a mistake, because it stops the loop before the work is complete.
Reading the arrow back to the top
Every loop drawing is checked the same way. Start at the top, and follow the arrows one by one, the way the program would run. Use real numbers. Stop when you reach the end box.
Use this check on the counter loop from worked example 1. Begin at the top with total = 0 and count = 0. Go down to the test: is count < 3? Yes, because 0 is less than 3. Follow the yes arrow into the body. Add scores[0], which is 72, to total. Add 1 to count. Follow the return arrow up to the test. Is count, now 1, less than 3? Yes. Keep going. When count is 3, the test says no, and the flow goes to the print box.
Doing the walk with numbers catches two kinds of error. The first kind is a return arrow that points to the wrong box. If the arrow goes back to the body instead of the test, the loop tests nothing on each pass, and the counter climbs past the list length. The second kind is a counter update that sits outside the loop. Those mistakes are invisible when you look at the drawing alone, and they appear as soon as you trace it with numbers.
Here is a short rule to remember. Every return arrow must go back to the test, not to the top of the picture and not to the body. Every loop must have a step inside the body that changes the value the test uses. Every break must leave by its own arrow to the step after the loop.
Common mistakes
Each mistake below comes from a real run of the program. The error messages are copied from the output.
Forgetting to change the counter
The first mistake is a loop whose counter never changes. The program runs forever, and it prints the same value again and again. This script has the update line left out.
count = 0
while count < 3:
print(count)The output does not stop. The first lines look like this:
0
0
0
0The loop never reaches the end, because count stays 0 and the test count < 3 is always yes. Stop a program like this with Ctrl+C, which is the usual key for stopping a running program in a terminal. The fix is to add the update, count = count + 1, inside the body.
Indentation that is off by one level
Python uses indentation to show which lines belong to the loop body. A line that should be in the body but is not indented causes an error before the program runs.
for i in range(3):
print(i)The error message is:
File "bad_indent.py", line 2
print(i)
^^^^^
IndentationError: expected an indented block after 'for' statement on line 1The message names line 1, the for line, because Python expected the body to start there. The fix is to indent print(i) by four spaces, so it sits inside the loop.
Using a variable that was never set
A variable that is used after the loop must have a value, even if the loop never ran. This program uses count after a loop that does not define it.
total = 0
for n in range(3):
total = total + n
print(count)The error message is:
File "undefined.py", line 4, in <module>
print(count)
^^^^^
NameError: name 'count' is not defined. Did you mean: 'round'?The name count is not used anywhere in the program before the print line, so Python does not know it. The fix is to give count a value before the loop, or to print a name that was set, such as total.
Reading past the end of a list
A sentinel loop needs a marker in the list. If the marker is missing, the loop keeps asking for the next value and runs off the end of the list. This program has a -1 marker, but after the loop it asks for position 3, which is past the end.
values = [4, 9, -1]
for v in values:
if v == -1:
break
print(v)
print(v)
print(values[3])The output and error message are:
4
9
-1
Traceback (most recent call last):
File "index.py", line 7, in <module>
print(values[3])
~~~~~~^^^
IndexError: list index out of rangeThe list has three values, at positions 0, 1 and 2. Position 3 does not exist, so the program stops with an IndexError. The fix in a sentinel loop is to stop when the position reaches the length of the list, as well as when the sentinel appears. Add that second test to the diamond in the flowchart.
Putting a break in the wrong place
A break placed before the answer is saved leaves the loop with nothing recorded. If the break in the temperature example came before first_hot_position = position, the program would always print -1, even when a hot reading exists. Trace the loop with one list that has a hot reading and one list that does not.
Practice
Each exercise is followed by its answer. Draw the flowchart first, then trace it with the numbers given, then check your answer.
Exercise 1
Draw a flowchart for a counter loop that counts how many numbers in the list [4, 7, 10, 3] are even. Use a counter called count, and a second counter called position for the list position. Trace the flowchart and give the final count.
Show the answer
The loop starts with position = 0 and count = 0. The test is position < 4. The body checks whether numbers[position] is even, and adds 1 to count if it is. Then the body adds 1 to position, and the return arrow goes to the test. The values 4 and 10 are even, so the final count is 2.
Exercise 2
Draw a sentinel loop that adds up the values in [3, 8, 5, -1, 20] until -1 appears. Give the total.
Show the answer
The loop reads 3, adds it to the total, reads 8, adds it, reads 5, adds it, then reads -1 and stops. The total is 3 + 8 + 5, which is 16. The 20 after the sentinel is not read.
Exercise 3
Draw a loop with a break that finds the position of the value 7 in the list [4, 9, 7, 2]. If 7 is not in the list, the answer is -1. Give the position found.
Show the answer
The loop checks position 0, which holds 4, and it is not 7. It checks position 1, which holds 9, and it is not 7. It checks position 2, which holds 7. The break runs, and the answer is 2.
Exercise 4
The flowchart for a counter loop has the update count = count + 1 outside the loop, after the end box. Describe what the program does, and say which arrow is wrong.
Show the answer
The update never runs inside the loop, so count stays at its starting value. If the test is count < 3 and the start is 0, the test says yes on every pass and the program never stops. The return arrow should go back to the test, and the update should sit inside the body, on the path between the yes arrow and the return arrow.
Exercise 5
Trace this loop by hand, then check it with a program. How many times does the body run, and what is the final value of count?
Show the answer
The body runs 3 times. The counter takes the values 5, 3 and 1 when the test is checked at the top of each pass. After the third pass, count is -1, and the test count > 0 says no. The program prints 3 -1.
Summary
- A loop is a test, a body and a return arrow that goes back to the test. Read the flowchart by following the arrows with real numbers.
- A counter loop repeats a set number of times, and its body must change the counter.
- A sentinel loop stops at a marker value, and it must read the next value before it tests it.
- A break leaves the loop at once, and its arrow goes straight to the step after the loop.
- Trace each drawing with a small list, and check that the return arrow goes back to the test.