← Back to the Introduction to Computer Science outline The Course Maker
← Introduction to Computer Science outline
Week 6 · Lecture

Lecture: Loops II: for, range & Nested Loops

Introduction to Computer Science Free sample edition

Lecture script · about 15–20 minutes spoken · Week 6

Opening

Think about a fitness app that adds up your steps for each of the seven days in a week. It doesn't test a condition to decide when the week is over. It handles day one, then day two, and stops after day seven.

A nursing student charts a reading every hour of a shift. A business major prints a price table row by row. Each of those programs repeats a step a known number of times, and each one has to know exactly where its count stops.

In Week 5 you met the while loop: you set up a counter, tested a condition at the top of every pass, and had to remember to move the counter. In Week 3 you learned that a slice keeps its start and drops its stop. This week the for loop does the counting for you, and its range stops the way a slice does.

Here's the plan for this lecture. We'll walk a string, repeat with range, read a range's stop, build a total, control where a line ends, nest one loop inside another, and check a chatbot's range with a run.

1. Walk a string: the for loop hands you each character

Picture a teacher calling roll. Nobody tells the teacher "now move to name number four." The teacher reads the first name, then the next, then the next, until the sheet runs out. Moving to the next name is built into reading down the sheet.

Python's version of that is the for loop. A for loop is a statement that runs its indented body once for each item of a sequence, handing the current item to a name before every pass. The sequence can be the characters of a string or the numbers of a range. That name has its own term. The loop variable is the name written between for and in, which Python sets to the next item of the sequence at the start of every pass, so it never needs an update line of its own.

Here's the first example. The line reads: for letter in the string "river", followed by a colon. Indented under it is one line that prints letter. On the first pass, letter holds r, and the body prints r. On the second pass, letter holds i. Then v, then e, then r again. The string has no sixth character, so the loop ends. Five characters gave five passes and five lines of output.

Notice what you didn't write: no counter, no condition, and no line that adds 1. That's also the classic mix-up this week. Students fresh from while loops sometimes add 1 to the loop variable inside the body, as if it were a counter. It doesn't move the loop along. The for line does the moving.

Pause and try this. The loop over "river" prints one character per line. How many lines does it print, and which character is on the third line?

Walk the word one letter at a time in your head.

Here's the answer. It prints five lines, one per character, and the third line is v. The loop variable took r, then i, then v on the first three passes.

So the for loop hands you each item, and you never move it yourself.

2. Repeat a known number of times with range

Think of a pill organizer with seven boxes, one for each day. You fill box one, box two, and so on through box seven, and then you're done.

When you know the count, you pair the for loop with range(). Range is the built-in that produces whole numbers from a start, 0 when none is given, up to but not including a stop, moving by a step that is 1 when none is given.

Here's the reading log's stage for this week. Pages_read starts at 45. Then the loop says: for day in range from 1 to 8. Inside the loop, pages_read gets pages_read plus 30, and the program prints day and pages_read on one line. After the loop, with no indentation, it prints pages_read once more.

On the first pass, day is 1, and 45 plus 30 is 75, so the line reads 1, then 75. The passes keep coming until day is 7. The range from 1 to 8 holds 1 through 7, and 8 minus 1 is 7, so there are seven passes. Seven days at 30 pages is 210 pages, and 45 plus 210 is 255. So the last line inside the loop reads 7, then 255, and the line after the loop prints 255.

Compare that with Week 5, where the while loop kept adding until it passed the goal of 300, needed 9 days, and overshot to 315. This for loop never looks at the goal. Reach for while when the stopping point depends on what happens inside the loop, and for for when you know the count ahead of time.

Pause and try this. Counting every line it prints, inside the loop and after it, how many lines does the reading-log program print in all?

Count the passes first, then look at the line after the loop.

Here's the answer. It prints eight lines. Seven come from the seven passes, from 1 and 75 to 7 and 255, and one more comes from the unindented print after the loop, which prints 255.

With a step of one, stop minus start is the number of passes.

3. Read a range: three forms and the exclusive stop

Picture a ticket roll at a deli counter that hands out tickets in order and ends before a certain ticket. A range works like that roll, and you choose where it starts, where it stops, and how big each jump is.

Range comes in three forms. With one number, that number is the stop, and the range starts at 0. With two numbers, you give the start and the stop. With three numbers, you give the start, the stop, and the step, which is the size of each jump. In every form, the same rule holds. The exclusive stop is the rule that the stop number of a range is never one of the numbers it produces, so range from 1 to 5 gives 1, 2, 3, and 4 but not 5.

A range doesn't display its numbers on its own, so there's a trick for seeing them: wrap the range in list, and print that. Lists themselves come later, in Week 9. With that trick, range of 5 prints 0, 1, 2, 3, 4. Five values, starting at 0 and stopping before 5. The pinned loop over range from 1 to 5 prints 1, 2, 3, 4 on one line. Range from 0 to 10 with a step of 3 prints 0, 3, 6, 9. And the length of range from 1 to 10 with a step of 3 is 3, because that range holds 1, 4, and 7.

Two mistakes are tempting here: believing that range of 5 starts at 1, and believing that a range from 0 to 10 ends on 10. It starts at 0, and it never ends on its stop.

Pause and try this. Range from 0 to 10 with a step of 2. Does it include 10?

Start at 0 and jump by 2 until you reach the stop.

Here's the answer. No. It holds 0, 2, 4, 6, and 8. The next jump would land on 10, and 10 is the stop, so it's left out.

No start means 0, and the stop is never in the range.

4. Build a total, and choose the right stop

A cashier totalling a receipt keeps a running sum that starts at zero. Week 5 called that running sum an accumulator, and a for loop is a natural home for one, because it hands you each number to add.

Here's the example. Total starts at 0. Then for n in range from 1 to 6, total gets total plus n. After the loop, the program prints total. The range holds 1, 2, 3, 4, and 5, so the total is 1 plus 2 plus 3 plus 4 plus 5, which is 15, and the program prints 15.

Now change one number. Make the range go from 1 to 5. The loop still runs without complaint, but now it adds only 1 plus 2 plus 3 plus 4, which is 10, and it prints 10. That's a logic error: the program ran and printed the wrong total. Its cause is an off-by-one in the range, the same family of bug you met with less-than and less-than-or-equal-to in Week 5.

So which range do you want? Say n is 5. Range of n gives 0, 1, 2, 3, 4. Range from 1 to n plus 1 gives 1, 2, 3, 4, 5, ending on n because the stop, n plus 1, is left out. Both make five passes; they hand the body different numbers.

Pause and try this. You want a loop that adds 1 through 5. You start the range at 1. What stop do you write, and why?

Remember which number a range leaves out.

Here's the answer. You write 6, which is n plus 1 when n is 5. The stop is never produced, so a stop of 6 makes 5 the last number added, and the total comes out 15.

To end on n, stop at n plus 1.

5. End a line where you choose

Picture a printer that types one character and then feeds a fresh sheet of paper. You want it to stay on the same line until the row is done.

Normally, print adds a line break after whatever it prints. You can change that with end=. It's the setting inside the parentheses of print that replaces the line break print normally adds after its output. End with a space leaves a space, and end with an empty string leaves nothing.

Here's a row of stars. The loop runs over range of 4, and each pass prints a star with end set to an empty string, so each star lands right after the one before it. After four passes, the row holds four stars. Then, after the loop, comes a print with nothing inside its parentheses. That bare print prints only a line break, which finishes the row.

The bare print matters. A download progress bar prints a hash mark five times with end set to an empty string. With a bare print after the loop, the word done lands on its own line. Without it, done is glued to the end of the bar.

Pause and try this. In the row of stars, the line after the loop is a print with empty parentheses. What does that line add to the output?

Think about what end took away inside the loop.

Here's the answer. It adds only a line break. Inside the loop, end replaced every line break with nothing, so the bare print is what ends the row and sends the next output to a new line.

End says what follows each print, and a bare print ends the row.

6. Put one loop inside another

Picture two coins flipped for a game. To list every outcome, you take heads on the first coin and run through both sides of the second, then take tails and run through both sides again. That's a loop inside a loop.

Python calls it a nested loop: a loop written inside the body of another loop, so the whole inner loop runs from start to finish on every pass of the loop around it. The outer loop is the loop whose body holds the other loop; each of its passes starts the inner loop again from the beginning. The inner loop is the loop that sits inside the body of the other loop and runs all of its passes before the loop around it moves on.

Here's the pinned example. The outer loop is for i in range of 2. Inside it, the inner loop is for j in range of 3, and the inner body prints i and j. On the outer loop's first pass, i is 0, and the inner loop runs all three of its passes, printing 0 0, 0 1, and 0 2. Only then does i move to 1, and the inner loop starts over: 1 0, 1 1, 1 2. That's six lines, which is 2 times 3. The outer loop's passes times the inner loop's passes is the number of lines.

The same shape draws a grid. An outer loop over range of 3 is the rows, an inner loop over range of 4 prints the stars with end set to an empty string, and a bare print after the inner loop finishes each row. The output is three rows of four stars. And the pinned table multiplies: an outer loop and an inner loop each run over range from 1 to 4, and the body prints i times j. The three rows read 1 2 3, then 2 4 6, then 3 6 9.

The classic mistake is to think the inner loop runs once, because it's written only once on the page. But it sits in the outer loop's body, so it starts over on every outer pass.

Pause and try this. The star grid has an outer loop over range of 3 and an inner loop over range of 4. How many lines does it print, and how many stars in all?

Count the outer passes, then count the stars on each one.

Here's the answer. It prints three lines, one per outer pass, and 12 stars in all. Each outer pass runs the inner loop's four passes in full, and 3 times 4 is 12.

The inner loop finishes every time, and lines equal outer passes times inner passes.

7. Check a chatbot's range by running it

Picture a friend giving you directions: take the third exit. You count the exits as you pass them rather than trusting a guess about where it is. A chatbot's code deserves the same care, and the way you count is to run it.

Suppose you ask a chatbot for a loop that displays the numbers 1 to 5 on one line. It writes a loop over range from 1 to 5 and says the output is 1, 2, 3, 4, 5. You paste the code into your browser runner and run it. The output is 1, 2, 3, 4. The chatbot treated the stop as the last number, which is the classic range slip. The fix is one character: range from 1 to 6, and the run then displays all five numbers.

A chatbot predicts likely text; it doesn't run your program. When you want the official word, the Python Tutorial's section 4.3 on docs.python.org is where range and its exclusive stop are written down. One honest limit of this lecture: break and continue also work inside a for loop. You met break with the while loop in Week 5, and more use of both comes later.

Pause and try this. A chatbot says the reading log's loop over range from 1 to 8 makes 8 passes. What will a run show?

Count stop minus start.

Here's the answer. The run shows seven passes, from day 1 to day 7, because 8 minus 1 is 7 and the stop is never produced. The chatbot counted the stop as a day.

The chatbot proposes, and the run decides.

Closing

Let me pull it together in the order we built it. A for loop makes one pass per item and sets its loop variable for you, so the loop over "river" prints five lines. A range repeats a known number of times, so the reading log's range from 1 to 8 makes seven passes and ends at 255. A range starts at 0 when you give no start, and its stop is never produced, so range from 0 to 10 with a step of 2 stops at 8. A total over range from 1 to 6 is 15, and a stop that's one too small gives 10 instead. End decides what follows each print, and a bare print ends the row. A nested loop prints outer passes times inner passes, so the 2 by 3 loop prints six lines. And every claim about a range gets checked by a run.

Next in this module come the slide deck, the Readings and Resources page, the lecture tutorial, the practice set, the quiz, and the Coding Lab. Then, in Week 7, Functions, you'll learn to package a piece of work once, give it a name, and use it again and again.


Built with The Course Maker · samples.thecoursemaker.com