Nested Data Structures and Multi-Level Iteration
For loops are the most common and natural way to iterate through list elements, using identical syntax to string iteration.
Try it: What a for Loop Hands You
What a Python for loop gives its loop variable from each kind of iterable: the characters of a string, the positions from range(len(word)), the elements of a list, (index, item) pairs from enumerate(), the numbers of range(start, stop, step), a dict's keys, its .values() and its .items() tuples unpacked into key, val, the inner lists of a nested list and the values an inner loop visits; and why removing items from a list while looping over it skips the next item, while looping over a copy nums[:] does not.
How it works
- The for statement asks the object for an iterator, then calls next() on it once per pass.
- Each next() result is bound to the loop variable (a tuple result such as ('a', 10) or (0, 'red') is unpacked into two names), and the indented body runs once with it.
- A string gives characters, a list gives element values (not positions), range() computes start, start + step, … stopping before stop, and a dict gives its keys in insertion order (.values() the values, .items() key-value tuples).
- A nested list's inner list is one element of the outer loop; a second, inner for loop is needed to visit the values inside it.
- A list iterator only remembers a position number into the live list: removing an item shifts the later items left, so the item that slides into the passed position is skipped. Looping over a copy (nums[:]) keeps the positions fixed.
- When next() has nothing left the loop ends (StopIteration) and the loop variable keeps its last value; an empty iterable runs the body zero times.
Default run (10 steps): A 3-line program. Step through it: each pass of the for loop asks the iterator for its next item, binds the loop variable to it and runs the indented body once. … Done: the loop body ran 3 times. Output: red | green | blue.
Simplified: The programs are twelve fixed templates: you choose the loop and edit only its data (a short string, list items that are words or integers, key: value pairs with word keys and integer values, range numbers from -20 to 20, up to 4 rows of integers, up to 10 numbers). Nothing you type is executed: the lab's own small parsers turn it into literals, and a model of CPython's iterator protocol written for these loops runs the program. Every program was also run in CPython 3.12 under sys.settrace, and the lab reproduces the variables before every line, the printed output, the final variables and the error.
Loading the simulation…
One Element at a Time
When a list contains several items, a for loop provides a direct way to visit each item in turn. The loop variable receives the actual element value during each iteration. It does not automatically receive the element's index.
red
green
blueReading the Outer List
A list traversal visits the list's elements in order. On the first iteration, the loop variable contains the first element; on the next iteration, it contains the next element; and so on until every element has been visited. You usually do not need to access each element manually by index. If an index is specifically required, the source notes that you can use range(len(list)) instead.
Tracing Three Iterations
Determine the values assigned to item while traversing ["A", "B", "C"].
- 1First iteration
item contains the first list element, "A".
- 2Second iteration
item contains the second list element, "B".
- 3Third iteration
item contains the third list element, "C".
The loop processes "A", then "B", then "C".
Nested Lists as Outer Elements
A nested list is still one element from the point of view of the outer list. If an outer list contains values and another list, the outer loop does not automatically visit the individual values inside that nested list. Instead, one iteration assigns the entire inner list to the loop variable.
groups = [["A", "B"], ["C", "D"]]
for group in groups:
print(group)The outer loop receives ["A", "B"] once and ["C", "D"] once.
groups = [["A", "B"], ["C", "D"]]
for group in groups:
for item in group:
print(item)The second loop visits A, B, C, and D inside the two inner lists.
Empty List Behavior
An empty list contains no elements to visit. Therefore, a for loop over an empty list performs zero iterations: the loop body never executes. This is expected behavior, not an error.
finishedPredicting the Output
What do you think happens?
What values are printed, and in what order, when the loop visits ["first", "second", "third"]?
Reveal answer
first, second, third
The loop variable receives each actual element value in list order. It does not automatically receive the indexes.
Predict the output before running this loop: values = ["north", "south"]. The loop prints each value as it visits the list.
Hints
- The loop variable receives actual values rather than indexes.
- Follow the list from its first element to its last element.
Mistakes with Loop Levels
Common mistake Assuming the loop variable contains an index
What it looks likeFor a list containing 10, 20, and 30, expecting the loop variable to be 0, 1, and 2.
Why it failsA standard for loop over a list assigns the actual element value to the loop variable.
Do this insteadReason about the values 10, 20, and 30. Use range(len(list)) when the index is needed.
Common mistake Assuming an outer loop automatically reaches inner values
What it looks likeExpecting one loop over [["A", "B"], ["C", "D"]] to process A, B, C, and D individually.
Why it failsEach inner list is one element of the outer list.
Do this insteadUse a second loop when the individual elements inside each nested list must be visited.
Common mistake Treating zero iterations as an error
What it looks likeExpecting the loop body to run once when the list is [].
Why it failsAn empty list has no elements, so there is nothing for the loop to assign to its variable.
Do this insteadExpect the loop body to execute zero times and continue with the code after the loop.
Before running a loop, write down the outer list's elements in order. For a nested list, keep each inner list grouped as one outer element. Only split that inner group into individual values when a second loop processes it.
Practice Traversal
For each case, predict how many times the loop body executes and what the loop variable receives: a list containing four ordinary values; an empty list; and a list containing two nested lists. Then explain what additional loop is needed to reach values inside the nested lists.
Hints
- Count the elements of the list being directly traversed.
- An empty list has no element for the loop variable.
- Treat each nested list as one element until a second loop traverses it.
Essential Takeaways
- 1A for loop visits list elements in order.
- 2The loop variable contains the actual element value, not the index.
- 3An empty list causes zero loop-body executions and is not an error.
- 4A nested list is one element of its outer list during outer-loop iteration.
- 5A second loop is needed to visit the individual elements inside each nested list.
At a glance
- A for loop traverses a list by assigning each actual element to its loop variable in order.
- The loop variable is a value, not an index.
- An empty list produces zero iterations.
- A nested list remains one outer element until another loop traverses its contents.
- Predict output by tracing the elements at the current loop level.