Nested loops and printed patterns¶
~15 min ยท prerequisite: Leaving a loop with break and continue
What you will be able to do¶
- Put one loop inside another, and predict how many times the inner block runs.
- Print rectangles and triangles with
print, usingend=""to stay on the same line andprint()to start a new one. - Use nested loops to count pairs and to build a multiplication total.
The idea¶
A nested loop is a loop inside the block of another loop. The outer loop runs its block once for each of its values. Each time the outer block runs, the inner loop runs all of its rounds from start to finish. If the outer loop has 3 values and the inner loop has 4, the inner block runs 12 times in total, which is 3 times 4.
Indentation shows the nesting.
The end argument of print, from the output lesson in Part 1, controls what is printed after the values. With end="", the next print continues on the same line. A call to print() with no values prints only the ending, which moves to a new line.
A break inside the inner loop leaves only the inner loop. The outer loop continues with its next value.
Worked example¶
Line by line, this is what Python does:
- The outer loop starts with
rowequal to 0. - The inner loop runs with
colequal to 0, 1, 2, and 3. Each run prints one*and leaves the cursor on the same line. - After the inner loop finishes,
print()moves to a new line. - The outer loop moves to
rowequal to 1, and the inner loop prints four more stars, followed by another new line. - The same happens for
rowequal to 2. The inner loop ran 3 times 4, which is 12 times.
The output is:
Try it¶
Each block checks its result with assert.
The second block captures the output in a StringIO buffer, the same way the Part 1 print lesson did, so the assert can check the exact text. The third block uses break in the inner loop only. For x equal to 0, the inner loop counts one pair and then breaks. For x equal to 1, it counts two pairs. For x equal to 2, it counts three pairs. The total is 6.
Common mistakes¶
-
Printing each star on its own line. Leaving out
end=""makes everyprintstart a new line:The output has six lines, each with one star. Add
end=""to the innerprint, and addprint()after the inner loop. -
Putting the newline call inside the inner loop. The following code prints a new line after every star:
The output has six lines, one star on each. Move
print()out of the inner loop, so it is indented under the outer loop only. -
Indenting the inner loop as if it were outside. The following code prints one long line instead of a grid:
The output is
************, with twelve stars on one line, because theprint()is not inside the outer loop. Check the indentation of each line. -
Expecting the inner loop to run only once. The following check fails:
The inner loop runs fully for each of the three rounds of the outer loop, so
runsis 12.
Practice¶
- Use two loops with
range(4)for the rows andrange(2)for the columns. Count the cells and assert that the count is 8. - Use nested loops over
range(3)foriandj. Addi + jto a total for every pair. Assert that the total is 18. - Use nested loops over
range(1, 7)foraandb. Count the pairs wherea * bequals 12, and assert that the count is 4. - Use nested loops to print a triangle of
+signs with 4 rows: one+in the first row, two in the second, and so on. Capture the output withredirect_stdoutand assert that it equals"+\n++\n+++\n++++\n". - Stretch: count the pairs
(i, j)with1 <= i < j <= 10whose sum is even. Assert that the count is 20. Hint: the inner loop can start ati + 1, usingrange(i + 1, 11).
Solution
-
python count = 0 for row in range(4): for col in range(2): count += 1 assert count == 8 -
python total = 0 for i in range(3): for j in range(3): total += i + j assert total == 18 -
python count = 0 for a in range(1, 7): for b in range(1, 7): if a * b == 12: count += 1 assert count == 4
The pairs are (2, 6), (3, 4), (4, 3), and (6, 2).
- ```python import io from contextlib import redirect_stdout
buffer = io.StringIO() with redirect_stdout(buffer): for row in range(1, 5): for col in range(row): print("+", end="") print() assert buffer.getvalue() == "+\n++\n+++\n++++\n" ```
python count = 0 for i in range(1, 11): for j in range(i + 1, 11): if (i + j) % 2 == 0: count += 1 assert count == 20
Pairs with both numbers odd, or both even, have an even sum. There are five odd and five even numbers from 1 to 10, and each group gives C(5, 2) = 10 pairs.
Recap¶
- An inner loop runs completely for each round of the outer loop, so the total number of runs is the outer count multiplied by the inner count.
print("*", end="")stays on the same line, andprint()starts a new line.- A
breakin the inner loop leaves only the inner loop.