3.2. Iteration#
When we need to iterate over the items in a collection or sequence, we typically use a for loop, which is specifically designed for this task. A for loop can loop through an object because the object is an iterable. An iterable is any Python object that can return its elements one at a time, allowing you to loop over it. Common Iterables in Python include:
Sequences: lists, tuples, strings, ranges
Collections: sets, dictionaries, frozensets
Files: file objects
Custom objects: anything implementing the iterator protocol
The ability to repeat a block of code is one of the most powerful features in programming. We call this iteration. Python provides two primary loop constructs to handle this:
forloops: Designed for definite iteration. Use these when you know in advance how many times code needs to run (e.g., iterating over a list of items).whileloops: Designed for indefinite iteration. Use these when you want to repeat a task as long as a specific condition is true, even if you don’t know exactly how many times that will be.
3.2.1. Iterators and Iterables#
Python iterators are objects that implement __iter__() and __next__(), which are special “dunder” (double-under) methods that define Python’s iterator protocol. You don’t call these directly; instead, you use the built-in functions iter() and next(), which invoke them internally. Iterables are objects that implement iter() and can return an iterator via the built-in iter() function.
Collections like lists, tuples, dictionaries, and sets are all iterable objects. They are iterable containers from which you can get an iterator using the iter() method:
tuple_fruit = ("apple", "banana", "cherry")
itr = iter(tuple_fruit) ### create iterator
print(next(itr)) ### iterator itr has a `next()` method
print(next(itr))
print(next(itr))
apple
banana
cherry
3.2.2. For Loops#
The for loops are mostly used when you have a block of code that you want to repeat a fixed number of times and to execute code for each item. With a for loop, you want to either:
iterate over the items in a data collection (such as
list,tuple,string, andrange, oriterate through a sequence of numbers using the
range()constructor, or using the index for index-based iteration.
In both situations, the number of iterations is known. There are times when we do not know the number of elements we are iterating through, e.g., when working with files, though.
for line in open('data.txt'):
print(line)
Commonly used for loop patterns are:
For Loop Type |
Typical Syntax |
Iterates Over |
Best Use Case |
Key Idea |
|---|---|---|---|---|
Basic for-each |
|
Elements |
Processing items |
Loop through values |
|
|
Numbers |
Counting, repeats |
Like a counting loop |
Index-based |
|
Index numbers |
When index needed |
Access by position |
|
|
Index + value |
Cleaner indexing |
Best practice |
Nested for loop |
|
Combinations |
Grids, tables |
Loop inside loop |
Note that other for loop patters include looping through objects such as dictionaries and files.
3.2.2.1. Loop through Iterables#
Python’s basic for loop works much like the foreach loop in other programming languages. Here’s the basic syntax:
for item in iterable:
<block>
In this syntax, we have:
the
forkeywordthe loop variable, item, which holds the current value in the target data collection
the body of a block of code that will run one iteration as the loop pulls one item from the iterable.
Once the loop finishes iterating over the data, the execution flow jumps to the next statement after the loop.
Here are two quick examples of a for loop in Python. In the first example, we use a for loop to traverse a list of fruit names. The loop body contains a call to print(), which displays each fruit in each loop.
3.2.2.1.1. Loop through lists#
fruits = ['apple', 'banana', 'cherry'] ### iterable object
for fruit in fruits:
print(fruit)
apple
banana
cherry
nums = [ 1, 2, 3, 4, 5 ]
for num in nums:
print(num**2, end=" ")
1 4 9 16 25
3.2.2.1.2. Loop through strings#
Note that this is character by character.
for letter in 'hello, world':
print(letter, end=' ')
h e l l o , w o r l d
### Exercise: Basic For Loop
# Write a for loop that iterates through the list `prices`
# and prints each price with a 10% tax added (price * 1.1).
prices = [10.00, 20.00, 100.00]
# TODO: Write your loop here
### your code ends here
11.0
22.0
110.00000000000001
3.2.2.2. Looping with range#
You use plain range(n) when you just need to repeat something *n* times.
for i in range(5):
print(i, end = " ")
0 1 2 3 4
3.2.2.3. Index-Based for Loop#
You use range(len(x)) specifically when you need the index to access x[i].
numbers = [10, 20, 30, 40]
for i in range(len(numbers)):
print(i, numbers[i]) ### numbers[i] is the value at that position
0 10
1 20
2 30
3 40
3.2.2.4. Nested Loops#
A nested loop is a loop inside the body of another loop. The “inner” loop finishes all of its iterations for every single iteration of the “outer” loop.
Syntax and Structure:
for outer_item in outer_sequence:
### outer loop body
for inner_item in inner_sequence:
# inner loop body executes for each outer_item
A classic use case is generating a multiplication table. For every number i (rows), we iterate through numbers j (columns).
for i in range(2, 9): # Outer loop (rows)
for j in range(2, 9): # Inner loop (columns)
print(f"{i*j}", end="\t")
print() # Newline after each row
4 6 8 10 12 14 16
6 9 12 15 18 21 24
8 12 16 20 24 28 32
10 15 20 25 30 35 40
12 18 24 30 36 42 48
14 21 28 35 42 49 56
16 24 32 40 48 56 64
Nested loops are essential for working with multi-dimensional data, like matrices (lists of lists).
matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
for row in matrix:
for item in row:
print(item, end=" ")
print() # Newline after printing a full row
1 2 3
4 5 6
7 8 9
### Exercise: Star Pattern
# Use a nested loop to print the following pattern of stars:
# *
# * *
# * * *
# * * * *
# * * * * *
# Hint: The outer loop controls the rows (range 1 to 6).
# The inner loop controls how many stars print on that row.
for row in range(1, 6):
# TODO: write the inner loop
print() # Newline after each row
*
* *
* * *
* * * *
* * * * *
3.2.2.5. Advanced for Loop#
Python provides several advanced techniques that make your code more elegant and readable:
enumerate()- getting index and valuezip()- parallel iterationLooping through dictionaries
3.2.2.5.1. Enumerate#
Use enumerate() when you need both the position and the value in a loop.
### enumerate example
fruits = ['apple', 'banana', 'cherry', 'date']
for index, fruit in enumerate(fruits):
print(f"{index}: {fruit}")
0: apple
1: banana
2: cherry
3: date
colors = ["red", "blue", "green"]
for index, color in enumerate(colors):
print(index, color)
0 red
1 blue
2 green
3.2.2.5.2. zip#
### zip example
names = ['Alice', 'Bob', 'Charlie']
ages = [25, 30, 35]
cities = ['New York', 'London', 'Tokyo']
for name, age, city in zip(names, ages, cities):
print(f"{name} \t {age} \t {city}")
Alice 25 New York
Bob 30 London
Charlie 35 Tokyo
3.2.2.5.3. Loop through Dictionaries#
person = {
'name': 'Alice',
'age': 25,
'city': 'New York',
'job': 'Engineer'
}
# Unpacking key-value pairs
for key, value in person.items():
print(f"{key}: {value}")
print()
# Unpacking keys only
for key in person.keys():
print(f"Key: {key}")
print()
# Unpacking values only
for value in person.values():
print(f"Value: {value}")
name: Alice
age: 25
city: New York
job: Engineer
Key: name
Key: age
Key: city
Key: job
Value: Alice
Value: 25
Value: New York
Value: Engineer
3.2.2.6. Accumulator Pattern#
Many loops exist to build up a single result from a collection: a total, a count, a product, or a new list. This is called the accumulator pattern, and it always has three steps:
Initialize the accumulator before the loop, to the value the result should have if the collection were empty:
0for a sum or a count,1for a product,[]for a list.Update the accumulator once per iteration inside the loop body, usually with an augmented assignment such as
+=.Use the result after the loop ends. Only then does the accumulator hold the final answer.
The example below adds up the prices in a shopping cart.
prices = [3.50, 1.25, 4.00, 2.25]
total = 0 ### 1. initialize before the loop
for price in prices:
total += price ### 2. update once per item
print(f"Total: ${total:.2f}") ### 3. use the result after the loop
Total: $11.00
A trace table shows how the accumulator changes on each iteration:
Iteration |
|
|
|---|---|---|
before the loop |
(none) |
0 |
1 |
3.50 |
3.50 |
2 |
1.25 |
4.75 |
3 |
4.00 |
8.75 |
4 |
2.25 |
11.00 |
Two mistakes are common. If you put total = 0 inside the loop, the accumulator is reset on every iteration and the result is only the last price. If you put the print() inside the loop, you see a running total after each item instead of one final answer.
The same three steps work for other kinds of results. Only the starting value and the update change:
nums = [1, 2, 3, 4, 5]
count = 0 ### counting: start at 0, add 1
product = 1 ### multiplying: start at 1, not 0
evens = [] ### collecting: start with an empty list
for num in nums:
if num % 2 == 0:
count += 1
evens.append(num)
product *= num
print("Even count:", count) # 2
print("Product:", product) # 120
print("Evens:", evens) # [2, 4]
Even count: 2
Product: 120
Evens: [2, 4]
### Exercise: Accumulator
# Initialize a variable `total_rainfall` to 0.
# Iterate through the list `weekly_rain`.
# Add each value to `total_rainfall` using the += operator.
# Print the total at the end.
weekly_rain = [1.2, 0.5, 2.3, 0.0, 1.1]
total_rainfall = 0
### TODO: your code starts here
print(f"Total rainfall: {total_rainfall}")
### TODO: your code stops here
Total rainfall: 0
Total rainfall: 5.1
3.2.3. while Loops#
A Python while loop repeatedly executes a block of code as long as a specified condition remains True. Once the condition evaluates to False, the program continues with the statement immediately following the loop.
Common patterns for using while loops include:
Type |
Controlled By |
Loop Continues While… |
Ends When |
Typical Use Case |
|---|---|---|---|---|
Counting (condition-controlled) |
A numeric counter |
Counter satisfies a condition (e.g., |
The counter’s condition becomes |
You know roughly how many repetitions you want, expressed as a number |
Sentinel (data-controlled) |
A special “stop” value in the incoming data |
The data value ≠ the sentinel |
The sentinel value shows up in the data |
Reading input/data of unknown length, until a specific stop signal appears (e.g., typing |
|
Nothing — the condition is always |
Forever, by default |
A |
Menus, games, event loops — situations where the exit condition is checked inside the loop, possibly in multiple places |
The core distinction of the three types of while loops are:
Counting — you’re tracking how many times you’ve looped.
Sentinel — you’re watching what value just came in.
while True — you’re not checking anything in the while line itself; the real exit logic lives inside the loop body via break.
The general syntax of the while loop is:
while [condition]:
[statement(s)] ### body; runs repeatedly when condition is True
times = 0
while times < 3:
print("Hello!")
times += 1
Hello!
Hello!
Hello!
The execution process of a while loop follows a specific cycle:
Evaluate: Python checks if the condition is True.
Execute: If True, the indented body runs.
Repeat: After the body finishes, execution jumps back to step 1.
Exit: If the condition evaluates to False, the loop stops, and the program proceeds to the code below it.
3.2.3.1. Counting while (Condition-Controlled)#
In a counting while loop:
A counter with initial value.
Loop repeats while a numeric condition remains true.
A
whileloop requires the counter as a variable to increment/decrement to be ready. In this example, we need to define an indexing variable, count.“Off-by-one errors”: Python indexing is
0-based, so use<instead of<=for aligned boundary.
count = 0 ### initialization of the variable
while count < 10: ### condition to check
print(count, end = " ")
count = count+1 ### update counter
0 1 2 3 4 5 6 7 8 9
3.2.3.2. Sentinel while Loop (Data-Controlled)#
In a sentinel while loop, the loop continues until a special value (the “sentinel”) is entered.
In the example below, fake_inputs simulates what a user types, using iter() and next() from the iterators section, so the code runs in the book. To try it with real keyboard input, enable Live Code, uncomment the input() lines, and comment out the next(fake_inputs) lines below them.
### fake_inputs simulates what a user types; uncomment the input() lines for actual use
fake_inputs = iter([5, 12, -1])
# number = int(input("Enter a number (-1 to quit): "))
number = next(fake_inputs)
while number != -1:
print("You entered:", number)
# number = int(input("Enter a number (-1 to quit): "))
number = next(fake_inputs)
print("Program ended.")
You entered: 5
You entered: 12
Program ended.
### Practice: Sentinel Loop
# Write a loop that keeps running until `user_input` is equal to "q".
# For testing in the book, get each value with `user_input = next(fake_inputs)`
# inside the loop instead of using input().
# Print each value as "You entered: <value>".
fake_inputs = iter(["apple", "banana", "q"])
### Your code starts here.
### Your code ends here.
You entered: apple
You entered: banana
You entered: q
3.2.3.3. while True loop (Infinite Loop with break)#
A while True loop is infinite by default — it doesn’t stop on its own, so you create a condition inside it to exit manually via break.
while True:
print("This runs forever")
In the code below, fake_inputs again simulates what a user types. To try it with real keyboard input, enable Live Code, uncomment the input() line, and comment out the next(fake_inputs) line below it.
### fake_inputs simulates what a user types; uncomment the input() line for actual use
fake_inputs = iter(["hello", "world", "q"])
while True:
# text = input("Enter something (q to quit): ")
text = next(fake_inputs)
if text == "q": ### when condition met
break ### break!!
print("You entered:", text)
print("Program ended.")
You entered: hello
You entered: world
Program ended.
Another example with number.
### fake_inputs simulates what a user types; uncomment the input() line for actual use
fake_inputs = iter([10, 20, 5, -1])
total = 0
while True:
# number = int(input("Enter a number (-1 to stop): "))
number = next(fake_inputs)
print("You entered:", number)
if number == -1:
break
total += number
print("Total:", total)
You entered: 10
You entered: 20
You entered: 5
You entered: -1
Total: 35
A while True loop in Python emulates the do while loop in languages like C, Java, or JavaScript, where the code block is run at least once before the condition is checked to decide whether to terminate. The syntax of the do while loop is:
do:
run code
while condition is true
In Java:
do {
System.out.println("Hello");
} while (x < 5);
3.2.4. Loop Control Statements#
You can control the execution of a for or while loop using the following statements:
break– Immediately exits the loop, even if the loop condition is stillTrue.continue– Skips the remainder of the current iteration and returns to the top of the loop to recheck the condition.pass- Used as a placeholder to write empty loops (also used for empty control statements, functions, and classes).elseclause – Executes only if the loop finishes normally (when the condition becomesFalse), and does not run if the loop is terminated by abreakstatement.
### 1/4. break statement for
for i in range(10):
if i == 5:
break
print(i, end = " ") ### output: 0 1 2 3 4
0 1 2 3 4
### 1/4. break statement while
i = 0
while i < 10:
print(i, end = " ")
if i == 5:
break
i += 1
0 1 2 3 4 5
### 2/4. continue statement for
for i in range(10):
if i == 5:
continue
print(i, end = " ")
0 1 2 3 4 6 7 8 9
continue + while is one of the most common infinite-loop bugs, that is, if you place your increment after the print() so continue would skip the increment forever.
### 2/4. continue statement while
i = 0
while i < 10:
i += 1
if i == 5:
continue
print(i, end = " ")
1 2 3 4 6 7 8 9 10
### 3/4. pass statement for for loop
for i in range(10):
pass # TODO: implement later
print(i)
9
### 3/4. pass statement for while loop
i = 0
while i < 10:
i += 1
pass ### TODO: do something later
print("after pass") ### this will run, after pass!!!
print('Value of i :', i)
after pass
after pass
after pass
after pass
after pass
after pass
after pass
after pass
after pass
after pass
Value of i : 10
### 4/4. else statement with loops
for i in range(10):
print(i, end=' ')
else:
print("Loop is over")
0 1 2 3 4 5 6 7 8 9 Loop is over
### 4/4. else statement with loops
i = 0
while i < 10:
print(i, end=' ')
i += 1
else:
print("Loop is over")
0 1 2 3 4 5 6 7 8 9 Loop is over
pass works similarly to continue in a while loop, with distinctions:
Feature |
|
|
|---|---|---|
Definition |
A null operation; it literally does nothing. |
Skips the remainder of the current loop iteration. |
Context |
Can be used anywhere (loops, functions, classes, |
Only allowed inside loops ( |
Impact on Flow |
Execution continues to the next statement in the block. |
Execution jumps back to the start of the loop for the next cycle. |
Primary Use |
Syntactic placeholder (prevents “empty block” errors). |
Logic control (skips specific items based on a condition). |
Example Scenario |
Creating an empty function for future implementation. |
Printing only odd numbers by skipping even ones. |
### Exercise: Break and Continue
# Loop through numbers from 1 to 20.
# 1. If the number is divisible by 4, skip it (use continue).
# 2. If the number is 18, stop the loop entirely (use break).
# 3. Otherwise, print the number.
for i in range(1, 21):
# TODO: check for 18 first (break)
# TODO: check for divisible by 4 (continue)
print(i, end=" ")
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
1 2 3 5 6 7 9 10 11 13 14 15 17