Array Indexing and Index Expressions
An array index can be an integer variable or an integer-valued expression, so the element accessed can change as the variable changes.
Predicting Before Reading the Mechanism
Imagine an array holding five stored values, and a loop whose counter starts at zero. The loop body runs once for each counter value and stops as soon as the counter reaches five. On each pass the body prints the element whose position matches the current counter value. Before you read further, try to predict what this program prints, and in what order. Making that prediction first will show you which parts of the mechanism you already understand and which parts need closer attention.
The rest of this article explains the mechanism behind that prediction. The central idea is that an array index does not have to be a fixed number written into the code. It can be held in an integer variable, or it can be any expression whose value is an integer. Because the variable can change while the written code stays the same, one line of code can reach different elements at different moments. That flexibility is one of the main reasons arrays are so useful.
Watching One Index Change
Think of the index variable as a pointer that moves through the positions of the array. Suppose the array holds the values 10, 20, 30, 40, and 50 at positions zero through four. If the variable i holds zero, the expression list[i] names the first position, which holds 10. If i then holds one, the same written text list[i] names the second position, which holds 20. The text list[i] never changes. Only the value of i changes, and that changed value redirects the access.
The diagram uses invented values for illustration. The point to notice is that each index names exactly one stored value. When i holds zero, the expression selects the element at position zero. When i holds two, the same expression selects the element at position two. The expression is evaluated fresh each time it is used, so its result follows whatever the variable holds at that moment.
Index Expressions Choose the Position
An index is not limited to a bare variable. It can be any expression whose value is an integer. Python evaluates the expression inside the square brackets first, and the result of that evaluation decides which element is accessed. An expression such as i plus one simply produces the position one greater than i. Because the expression is computed before the element is read, it can combine the loop counter with other integers to reach a position that is offset from the current one.
Evaluating an index expression
The array values are [10, 20, 30, 40, 50]. What does values[i + 1] select when i holds 2?
- 1Find the value of i
The variable i holds 2.
- 2Evaluate the index expression
i + 1 becomes 2 + 1, which is 3.
- 3Select the element
values[3] names the element at position three, which holds 40.
values[i + 1] selects 40 when i holds 2.
Walking Every Element with a Counting Loop
A for loop is the natural tool for visiting every element of an array, because its counter can serve as the array index itself. The loop variable starts at zero, the body runs once per value, and the variable increases after each pass. The continuation condition compares the variable with the array's length, and the loop continues only while that comparison holds. For printing every element of an array named values, the loop has this shape:
10
20
30
40
50len(values)returns the array's length, which is 5 here.range(len(values))produces the counter values 0, 1, 2, 3, 4.- values[i] uses the counter as the index, so each pass reads the next position.
On the first pass the counter holds zero, so the body reads the value at position zero. On the second pass the counter holds one, and the body reads the value at position one. The pattern continues until the counter equals five. At that point the continuation condition is false and the loop stops. The body never runs with the counter at five, which is why the last printed element is the one at position four. The loop visits the indices in order, so the printed output follows the order of the positions in the array.
Mistakes with the Loop Boundary
Common mistake Using less than or equal to length as the loop condition
What it looks likefor i in range(len(values) + 1): print(values[i])Why it failsThe valid positions run from zero through length minus one. When i reaches length, it names a position that does not exist in the array.
Do this insteadKeep the counter below the length, for example by using range(len(values)), which stops before the length value.
Common mistake Treating the length as the last valid index
Why it failsThe length is one more than the last valid index. An array of five items has length 5 but its last index is 4.
Do this insteadRemember that the last valid index is length minus one.
Common mistake Assuming the written expression always selects the same element
What it looks likeprint(values[i]) prints 10, then 20, then 30 as i changesWhy it failsThe text values[i] stays fixed, but the value of i changes on each pass, so the selected element changes too.
Do this insteadTrack the current value of the index variable before deciding which element is read.
Summing and Averaging Elements
Processing an array often means combining its elements rather than printing them. Suppose you have an array of double values and want its average. The plan has two stages. First, a loop adds every element into a running total that starts at zero. Second, the total is divided by the number of items in the array to produce the average. The division happens once, after the loop has finished.
30.0- total starts at zero, so it is ready to accumulate.
- The loop body adds one element on each pass; the loop itself is the same counting pattern used for printing.
- The division by
len(values)happens once, after the loop ends.
Tracing the sum and average
Trace the loop for the array [10.0, 20.0, 30.0, 40.0, 50.0] and find the average.
- 1Start the total
total is set to 0.0 before the loop begins.
- 2Process the first elements
Adding 10.0 gives 10.0, then adding 20.0 gives 30.0.
- 3Process the remaining elements
Adding 30.0 gives 60.0, adding 40.0 gives 100.0, and adding 50.0 gives 150.0.
- 4Divide once
After the loop, the total 150.0 is divided by
len(values), which is 5.
The average is 30.0.
Initialize the accumulator to a starting value before the loop, update it inside the loop body on every pass, and perform the final division after the loop has finished. Keeping the division outside the loop means it is computed once rather than on every pass.
Predicting a Loop's Last Output
What do you think happens?
For the array [10, 20, 30, 40, 50] with the loop shown earlier, what is the last value printed?
Reveal answer
50
The counter visits 0 through 4. On the pass where the counter is 4, the body reads values[4], which holds 50. The counter then reaches 5, the condition is false, and the loop stops.
An array named scores holds the values 7, 3, 9, and 5. Trace a loop with a counter from 0 up to but not including len(scores) that prints scores[i] plus 1 on each pass. List the printed numbers in order, then state which index is read last and why.
Hints
- The array has length 4, so the counter takes the values 0, 1, 2, and 3.
- Add 1 to each element inside the body before printing.
- The last index read is length minus one.
Key Takeaways
- An array index can be an integer variable or any integer-valued expression, so the same written expression can select different elements as the variable changes.
- A for loop whose counter runs from zero while the counter is less than the array's length visits every element once, in order from index zero upward.
- The strict less-than stopping rule keeps the loop inside the array, because valid positions run from zero through length minus one.
- To average an array, a loop adds each element into a running total that starts at zero, and the total is divided by the array length once after the loop.