For Loops and String Iteration
The name item is a loop variable. During one iteration it contains one actual list element. On the next iteration, it contains the next element. It is not an index such as 0, 1, or 2.
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 you have a list of items, you often need to do something with each item in turn. A for loop provides a clean way to visit every element without manually accessing each element by its index. The loop moves through the list in order, and the loop variable receives the actual element value during each iteration.
What do you think happens?
Suppose a loop visits the list ["red", "green", "blue"]. What value does the loop variable receive first, and what values follow?
Reveal answer
The loop variable receives "red", then "green", then "blue".
A for loop over a list visits the actual elements. It does not place the element indexes in the loop variable.
The Traversal Sequence
items = ["red", "green", "blue"]
for item in items:
print(item)- 1The list named items is the collection being traversed.
- 2The first iteration assigns "red" to item and executes the loop body.
- 3The second iteration assigns "green" to item and executes the loop body again.
- 4The third iteration assigns "blue" to item and executes the loop body again.
- 5After every element has been visited, the loop has no further list element to process.
- The list contains three elements.
- The loop variable item receives the first element, then the second, then the third.
- The loop body prints the current value on each iteration.
red
green
blueThe name item is a loop variable. During one iteration it contains one actual list element. On the next iteration, it contains the next element. It is not an index such as 0, 1, or 2.
Reading the Loop Variable
Predicting Each Iteration
A loop traverses the list [10, 20, 30]. What does the loop variable contain on each pass?
- 1First pass
The loop variable contains the first element, 10.
- 2Second pass
The loop variable contains the next element, 20.
- 3Third pass
The loop variable contains the final element, 30.
- 4Index check
The loop variable contains 10, 20, and 30, not the indexes 0, 1, and 2.
The loop processes the values 10, 20, and 30 in that order.
Nested Lists Stay Whole
A nested list is still one element of its outer list. When a for loop traverses the outer list, it does not automatically enter the inner lists. Each inner list is delivered to the loop variable as one complete value during one iteration.
['a', 'b']
['c', 'd']The outer loop has two iterations in this example because the outer list has two elements. Those elements happen to be lists, but each inner list is treated as one element by the outer loop.
Empty List Behavior
An empty list contains no elements to visit. Therefore, a for loop over an empty list executes its loop body zero times. Nothing inside the body is processed, and this is expected behavior rather than an error.
doneStrings Use the Same Pattern
The syntax for iterating over a list is identical to the syntax used for iterating over a string. In both cases, the for loop assigns the next element of the sequence to the loop variable and processes that value before moving on.
| Collection | Value received by the loop variable | Traversal idea |
|---|---|---|
| List | Each list element | Visit the list elements in order |
| String | Each character | Visit the string characters in order |
The for-loop pattern is shared: the loop variable receives the next element during each iteration.
Mistakes in Prediction
Common mistake Assuming the loop variable contains an index
What it looks likefor item in ["a", "b"]: the loop variable item receives "a" and then "b".Why it failsA direct for loop over a list assigns actual element values to the loop variable, not element indexes.
Do this insteadPredict the element values first. Use range(len(list)) when the task specifically requires indexes.
Common mistake Expecting a nested list to be unpacked automatically
What it looks likeFor an outer list containing ["a", "b"] as one element, one iteration receives ["a", "b"] as a complete list.
Why it failsNested lists are treated as single elements during iteration of the outer list.
Do this insteadCount the elements of the outer list first. An inner list contributes one outer iteration.
Common mistake Treating an empty-list loop as an error
What it looks likeA loop over [] runs its body zero times.
Why it failsThere are no elements available for the loop to process, so no iteration is expected.
Do this insteadPredict no loop-body output and continue reasoning about the statements after the loop.
Prediction Practice
Before running the loop, write down the value of item on every iteration and the order of the printed output.
items = ["first", ["inside", "list"], "last"]
for item in items:
print(item)Hints
- Count the elements in the outer list.
- Treat the nested list as one outer element.
- The loop variable receives values, not indexes.
Checking the Prediction
Determine the loop-variable values for ["first", ["inside", "list"], "last"].
- 1First iteration
The loop variable receives the string "first".
- 2Second iteration
The loop variable receives the nested list ["inside", "list"] as one complete element.
- 3Third iteration
The loop variable receives the string "last".
The loop processes three outer elements in order: "first", ["inside", "list"], and "last".
Key Takeaways
- 1A for loop is a natural way to visit every element of a list in order.
- 2The loop variable holds the actual element value, not its index.
- 3An empty list causes zero loop-body executions and is not an error.
- 4A nested list is treated as one element when iterating through its outer list.
- 5List and string iteration use the same for-loop syntax pattern.
At a glance
- For loops traverse list elements one at a time and in order.
- The loop variable receives each actual element rather than an index.
- Nested lists count as single elements during iteration of the outer list.
- An empty list produces no loop-body iterations.
- String iteration follows the same basic pattern as list iteration.