Introduction
In this lesson, you will move beyond basic for and while syntax and learn how to structure loops to solve common real-world problems. We’ll focus on reusable loop patterns and idioms that appear in almost every Python program:
- Choosing between
for,while, and nested loops - Counter-controlled loops (fixed repetition and aggregations)
- Searching, filtering, and selecting items in sequences
- Accumulators and running totals (sums, counts, and averages)
- Using
break,continue, and flags to manage complex loop flows
You already know how loops work mechanically; now you’ll learn to recognize and apply patterns that make your code clearer and more efficient.
Choosing Between for, while, and Nested Loops
When to Use for
Use a for loop when:
- You know how many times you need to repeat something, or
- You are iterating over a sequence (list, string, range, etc.).
Example: process each item in a shopping cart exactly once.
cart = [10.99, 4.50, 2.75]
for price in cart:
tax = price * 0.1
print(f"Price: {price}, Tax: {tax}")
# Output
Price: 10.99, Tax: 1.099
Price: 4.5, Tax: 0.45
Price: 2.75, Tax: 0.275
Here the number of iterations is determined by the number of items in cart, so for is the natural choice.
When to Use while
Use a while loop when the number of repetitions is not known in advance and depends on a changing condition.
Example: keep asking for input until the user types quit.
command = ""
while command != "quit":
command = input("Enter a command (or 'quit' to exit): ")
print(f"You entered: {command}")
# Output (example interaction)
Enter a command (or 'quit' to exit): run
You entered: run
Enter a command (or 'quit' to exit): status
You entered: status
Enter a command (or 'quit' to exit): quit
You entered: quit
The loop continues based on the state (command), not on a fixed count.
When to Use Nested Loops
Use nested loops when you need to combine or compare every element of one sequence with every element of another, or iterate through multi-dimensional data.
Example: generate all (row, column) positions in a grid.
rows = 3
cols = 2
for r in range(rows):
for c in range(cols):
print(f"Cell: ({r}, {c})")
# Output
Cell: (0, 0)
Cell: (0, 1)
Cell: (1, 0)
Cell: (1, 1)
Cell: (2, 0)
Cell: (2, 1)
Each inner-loop iteration pairs a column with the current row from the outer loop.
Counter-Controlled Loops and Fixed Repetition
A counter-controlled loop uses a variable (counter) to run the loop a fixed number of times.
Fixed Repetition Task
times = int(input("How many stars should I print? "))
for i in range(times):
print("*", end="")
print() # newline
# Output (if user enters 5)
How many stars should I print? 5
*****
range(times) creates exactly times iterations; i acts as a counter even though we don’t use its value directly.
Aggregation with a Counter
Counter-controlled loops often appear in aggregations, like computing the total of several inputs.
n = int(input("How many numbers? "))
total = 0
for i in range(n):
value = float(input(f"Enter number {i + 1}: "))
total += value
print("Total:", total)
# Output (example)
How many numbers? 3
Enter number 1: 2.5
Enter number 2: 1.5
Enter number 3: 6
Total: 10.0
The counter i ensures we ask for exactly n numbers and accumulate them into total.
Loop Patterns for Searching, Filtering, and Selecting
Linear Search Pattern
The search pattern walks through a sequence looking for the first element that matches a condition.
numbers = [3, 10, 7, 21, 5]
target = 21
found_index = None
for i, num in enumerate(numbers):
if num == target:
found_index = i
break
if found_index is not None:
print(f"Found {target} at index {found_index}")
else:
print(f"{target} not found")
# Output
Found 21 at index 3
We maintain found_index as the result of the search and use break to stop as soon as we’ve found the target.
Filtering Pattern
The filtering pattern builds a new collection containing only items that satisfy a condition.
scores = [95, 62, 88, 47, 73, 100]
passing_scores = []
for score in scores:
if score >= 70:
passing_scores.append(score)
print("Passing:", passing_scores)
# Output
Passing: [95, 88, 73, 100]
Instead of modifying the original list, we create a new list and selectively append items.
Selecting Best (or Worst) Item
The selection pattern finds an item with the minimum/maximum value based on some criterion.
prices = [19.99, 5.49, 12.30, 3.99]
cheapest_price = prices[0]
for price in prices[1:]:
if price < cheapest_price:
cheapest_price = price
print("Cheapest price:", cheapest_price)
# Output
Cheapest price: 3.99
We start with the first element as the current best and update it whenever we find a better candidate.
Accumulator and Running Total Idioms
An accumulator variable keeps a running result across loop iterations (sum, count, product, etc.).
Sum and Count for Average
numbers = [4, 8, 15, 16, 23, 42]
count = 0
sum_values = 0
for num in numbers:
sum_values += num
count += 1
average = sum_values / count if count > 0 else 0
print("Sum:", sum_values)
print("Count:", count)
print("Average:", average)
# Output
Sum: 108
Count: 6
Average: 18.0
Here, sum_values and count are accumulators updated each iteration. This idiom generalizes to any metric you want to collect.
Multiple Accumulators
You can maintain several running totals at once.
transactions = [100, -20, 50, -10, -5]
deposits = 0
withdrawals = 0
for amount in transactions:
if amount > 0:
deposits += amount
else:
withdrawals += -amount # store withdrawals as positive totals
print("Total deposits:", deposits)
print("Total withdrawals:", withdrawals)
# Output
Total deposits: 150
Total withdrawals: 35
Different accumulators track different aspects of the same data.
Controlling Complex Loop Flows: break, continue, and Flags
You’ve already seen simple break and continue usage. Now we’ll combine them with flags to manage more complex logic.
Using Flags to Track Conditions Across Iterations
A flag variable is a boolean that remembers whether something has happened during the loop.
Example: check if any number is negative.
values = [5, 3, 0, -1, 7]
has_negative = False
for v in values:
if v < 0:
has_negative = True
break
if has_negative:
print("There is at least one negative value.")
else:
print("All values are non-negative.")
# Output
There is at least one negative value.
The flag has_negative summarizes the result of the loop.
Combining continue with Flags
Sometimes you want to skip some iterations but still keep overall state.
lines = [
"# Comment line",
" ",
"value1=10",
"value2=20",
]
non_empty_lines = 0
for line in lines:
stripped = line.strip()
if stripped == "":
continue # skip blank lines
if stripped.startswith("#"):
continue # skip comments
non_empty_lines += 1
print("Number of meaningful lines:", non_empty_lines)
# Output
Number of meaningful lines: 2
continue jumps to the next iteration for lines we don’t care about, while non_empty_lines accumulates useful ones.
Nested Loops with break and Flags
In nested loops, break only exits the inner loop. Flags help when you need to influence the outer loop based on inner-loop results.
matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
]
target = 5
found = False
for r, row in enumerate(matrix):
for c, value in enumerate(row):
if value == target:
print(f"Found {target} at ({r}, {c})")
found = True
break # exits inner loop
if found:
break # exits outer loop
if not found:
print("Target not found")
# Output
Found 5 at (1, 1)
The found flag allows the outer loop to know that the inner loop has already located the target and can stop.
Summary / Key Takeaways
In this lesson on Common Loop Patterns and Idioms, you have learned:
- Choosing Loop Types: Use
forfor known-length or sequence-based iteration,whilefor condition-driven repetition, and nested loops for multi-dimensional or combinatorial processing. - Counter-Controlled Repetition: Apply counters with
range()to perform fixed numbers of iterations and to structure input collection and iteration bounds. - Aggregation Patterns: Use accumulators inside loops to compute totals, counts, and derived values like averages, sometimes with multiple accumulators in the same loop.
- Searching Idioms: Implement linear search patterns that scan sequences, track indices or flags, and often exit early with
breakwhen a match is found. - Filtering and Selection: Build new collections by filtering items that satisfy conditions and select best/worst elements using running comparisons.
- Flags for Loop State: Maintain boolean flag variables to remember whether events occurred during iteration and to simplify post-loop decisions.
- Flow Control with
breakandcontinue: Combinebreakandcontinuewith loop patterns to stop early, skip irrelevant items, and keep loop bodies focused. - Nested Loops with Coordination: Coordinate outer and inner loops using flags and conditional breaks to manage complex searches or multi-level iteration.
