Nested Loops and Complex Iterations
A for loop traverses a string by automatically assigning each character to a loop variable, one character per 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…
A Character at a Time
A for loop can visit every character in a string without requiring you to manage index numbers yourself. During each iteration, Python assigns the next character to the loop variable, runs the loop body, and then continues to the next character. The loop stops after all characters have been visited.
Mapping Positions to Characters
Consider the string banana. It contains six characters. A string index identifies a position, while a for loop assigns the character at that position to the loop variable. The loop does not display the index; it exposes the character itself. The repeated a and n characters are visited because they occur at separate positions in the string.
The diagram shows the relationship between positions and loop values. At the first position, char receives b. At the next position, it is reassigned to a, and this continues in order until the final a. The variable is reused, but its value changes at every iteration.
Tracing Every Iteration
What do you think happens?
If a loop visits the string banana and prints the loop variable once per iteration, what characters will it print in order?
Reveal answer
banana
The loop visits all six characters in order: b, a, n, a, n, and a. It prints characters rather than their index numbers.
A useful trace records two things for every iteration: the current value of the loop variable and the action performed by the loop body. After the body runs for b, control returns to the loop so the variable can receive a. The same process repeats for n, a, n, and a. Once the final character has been processed, there is no next character, so the loop stops automatically.
Writing the Loop
In a string-traversal loop, the variable after for holds the current character, the value after in is the string being traversed, and the indented body contains the processing performed for each character. The keyword in tells Python to iterate through the string's elements.
b
a
n
a
n
a| Part | Role |
|---|---|
| char | The loop variable that receives one character at a time |
| in | The keyword that introduces the values being traversed |
| fruit | The string being traversed |
| print(char) | The loop body that runs for each character |
Parts of a string-traversal for loop
Following Control Flow
The loop body is not the whole loop. After the body processes the current character, control returns to the iteration mechanism. Python assigns the next character to the loop variable and runs the body again. This automatic progression is why you do not need to increment an index or manually test whether the end of the string has been reached.
Choose a loop variable name that communicates its role. Names such as char or letter make it clear that the variable represents one character, although Python allows you to choose another name.
Diagnosing Unexpected Traversal
When the output is not what you expected, trace the loop one iteration at a time. Write down the character assigned to the loop variable and the action performed by the body. Compare that trace with the characters in the original string in order. The first difference identifies where the loop's observed behavior diverges from your expectation.
Common mistake Expecting the loop variable to contain an index number.
What it looks likeA trace records char as 0, 1, 2, 3, 4, and 5 instead of b, a, n, a, n, and a.
Why it failsA for loop over a string assigns each character directly to the loop variable.
Do this insteadTrace the character value held by the variable at each iteration.
Common mistake Assuming repeated characters were skipped.
What it looks likeThe two occurrences of a in banana are treated as one visit.
Why it failsThe loop visits positions in order, so repeated characters at different positions are visited separately.
Do this insteadRecord each iteration in sequence, even when the character value is the same as one seen earlier.
Common mistake Adding manual stopping or index management to a simple traversal.
What it looks likeThe loop includes extra logic to increment an index or check whether the string has ended.
Why it failsThe for loop automatically continues until all characters have been visited.
Do this insteadLet the for loop handle progression and termination when your task is to process every character.
Common mistake Looking only at the loop header and ignoring the indented body.
What it looks likeThe character sequence is traced correctly, but the expected result does not match what the body actually does.
Why it failsThe body runs once for every character and determines the processing performed at each step.
Do this insteadRecord both the current character and the body's action during every iteration.
Choosing the Clearer Approach
| For loop over a string | Manual index-based traversal |
|---|---|
| The loop variable receives each character directly. | The programmer tracks index positions manually. |
| Python handles progression through the string. | The programmer must remember to advance the index. |
| Python handles stopping after all characters are visited. | The programmer must check whether the end has been reached. |
| The intent to visit every character is immediately visible. | Index arithmetic can make the intent less direct. |
Why a for loop is generally simpler for visiting every character
A while loop with manual index tracking can also traverse a string, but a for loop is simpler and less error-prone for this purpose. It avoids manual index increments and end checks. It also communicates the intent clearly: visit each character and run the body once for each one.
Practice the Trace
Suppose a for loop traverses the string banana. Create a six-row trace. For each row, record the iteration number, the character held by the loop variable, and the action performed by a loop body that prints the character. Then explain why the loop stops after the sixth row.
Hints
- The string contains six characters.
- Begin with b and preserve the original order.
- The loop stops when there are no characters left to visit.
Write a for loop that traverses a string stored in a variable named fruit and processes each character by printing it. Before running the loop, predict the sequence of characters that will be processed when fruit contains banana.
Hints
- Use a loop variable such as char or letter.
- Place the string variable after in.
- Put the processing statement inside the indented loop body.
Key Takeaways
- 1A for loop over a string assigns one character to its loop variable per iteration.
- 2The loop visits characters in their string order and continues until all characters have been visited.
- 3The loop variable contains the character, not the index number, although each iteration corresponds to an index position.
- 4Tracing the variable and loop body step by step helps predict output and locate unexpected behavior.
- 5For loops are usually clearer and less error-prone than manual index-based traversal when processing every character.
At a glance
- A for loop automatically assigns each character in a string to a loop variable.
- For the string banana, the loop receives b, a, n, a, n, and a in that order.
- Tracing each iteration connects the loop variable to the corresponding string position.
- The loop handles progression and termination automatically.
- Manual tracing is a practical way to debug unexpected string-traversal behavior.