Understanding List Indices
Index-based iteration combines range() and len() to generate indices, enabling you to read and modify list elements.
A List That Changes
Suppose a list contains numbers that must all be doubled. The important question is not only which values are in the list, but also which position each value occupies. Index-based iteration gives the loop an index for each position. The loop can then read the old value at that position and assign a new value back to the same position.
What do you think happens?
A list starts as [3, 5, 7]. If a loop doubles the value at each index, what will the final list be?
Reveal answer
Answer: [6, 10, 14]
Each iteration reads the value at the current index, doubles it, and writes the result back to that same position. Tracing the positions in order shows every element changing once.
Following Positions
An index identifies a position in the list. In the illustration, index 0 is paired with 3, index 1 with 5, and index 2 with 7. When a loop variable i holds one of these indices, numbers[i] selects the value at that position.
Generating Valid Indices
The combination range(len(numbers)) produces the sequence of indices used to visit the elements of numbers. len(numbers) supplies the list's length, and range() uses that length to generate the positions for the loop. The loop variable receives one generated index at a time.
The expression numbers[i] appears on both sides of the assignment. On the right, it reads the old value at index i. Multiplication creates the replacement value. On the left, numbers[i] identifies the position where that replacement is written.
Reading and Replacing
Doubling Every Element
Trace the loop for numbers = [3, 5, 7] and determine the final list.
Index 0: The old value at index 0 is 3. The assignment calculates 3 * 2 and writes 6 back to index 0. The list becomes [6, 5, 7].
Index 1: The old value at index 1 is 5. The assignment calculates 5 * 2 and writes 10 back to index 1. The list becomes [6, 10, 7].
Index 2: The old value at index 2 is 7. The assignment calculates 7 * 2 and writes 14 back to index 2. The list becomes [6, 10, 14].
The final list is [6, 10, 14].
Tracing the Final State
Tracing means recording the list after each iteration instead of jumping directly to the answer. At the beginning, the list is [3, 5, 7]. After index 0, it is [6, 5, 7]. After index 1, it is [6, 10, 7]. After index 2, it is [6, 10, 14]. This sequence shows exactly which element changed at each step.
For a trace, write down three things at every iteration: the current index, the old value selected at that index, and the complete list after the assignment. This makes the final state a consequence of visible steps rather than a guess.
Choosing an Iteration Style
| Iteration need | Suitable approach | Reason |
|---|---|---|
| Only read each value | Value-based iteration | The value itself is sufficient. |
| Update elements in the list | Index-based iteration | The index identifies where the replacement is written. |
Use value-based iteration when the task only requires reading the values. Use index-based iteration when the task requires updating list elements, because the index tells the assignment which position should receive the new value.
Common Tracing Mistakes
Treating numbers[i] on the right side as the new value
The right side is evaluated first, so numbers[i] initially supplies the old value at index i.
Fix:
Read the statement as: select the old value, calculate the replacement, then write it back to the same position.Updating only the value in your written trace
The loop changes one list element at a time, but the complete list is needed to trace later iterations.
Fix:
Record the whole list after every assignment.Choosing value-based iteration for an update task
The task needs the position where the replacement belongs.
Fix:
Use range(len(numbers)) so the loop variable supplies an index for the assignment.
Practice the Trace
Trace this loop by writing the complete list after each index is processed, then state the final list: values = [2, 4, 6]; for i in range(len(values)): values[i] = values[i] * 2
Hints
- List the indices generated by range(len(values)).
- At each index, read the old value before calculating its replacement.
- Change only the selected position in your written list.
Practice Check
Complete the trace for values = [2, 4, 6] when every selected value is doubled.
Index 0: The old value is 2, so the list becomes [4, 4, 6].
Index 1: The old value is 4, so the list becomes [4, 8, 6].
Index 2: The old value is 6, so the list becomes [4, 8, 12].
The final list is [4, 8, 12].
Key Takeaways
- range(len(list)) generates indices for iterating through a list by position.
- In list[i] = list[i] * 2, the right side reads the old value and the left side writes the new value to the same position.
- Index-based iteration is appropriate when list elements must be updated.
- Value-based iteration is sufficient when values only need to be read.
- Tracing the list after each iteration reveals the final state.
Key Takeaways
- Use range(len(list)) to obtain indices that move through the list.
- An indexed assignment reads an old element value and writes a replacement to that element's position.
- Choose index-based iteration for updates and value-based iteration for read-only work.
- Trace the index, old value, and complete list state at every iteration to predict the result.