next up previous contents
Next: while loops Up: Programming Previous: for loops   Contents

for loops and the range function

The for loop is very handy for processing a sequence of values, but there are several very common problems which the for loop can't handle by itself. First, changing the value of the for loop variable (var) does not change the value of the corresponding element in sequence. For example, suppose we tried to change the value of each element in an array to zero by using the for loop variable on the left-hand side of an assignment statement:
>>> x = [1,2,3,4,5]
>>> for i in x:
...     i = 0
...
>>> x
[1, 2, 3, 4, 5]
The value of the elements in x was not changed, because the for loop variable represents only a copy of the value of the corresponding element in the sequence, not the actual element itself. Notice that if the elements of the sequence being iterated over are mutable objects, then elements stored within those objects can be changed by refering to the appropriate element of the loop variable. Consider the following array, whose elements are each another array. We could replace the first element of each of the array elements with zero using a for loop:
>>> dblarray = [[7,12,9],[13,8,3],[19,2,14]]
>>> for d in dblarray:
...     d[0] = 0
...
>>> dblarray
[[0, 12, 9], [0, 8, 3], [0, 2, 14]]

Another example is the case of creating a new sequence by processing one or more other sequences. Suppose we have an array of prices and an array of the same length containing taxes, and we wish to create a third array which has the total of the prices and the taxes for each of the items represented in the two arrays. Clearly, the for loop as presented so far has no means of dealing with this problem. If you're familiar with other programming languages, you'll notice that these two tasks are quite simple in most other languages, at the cost of either a complex syntax or additional looping constructs.

In python, problems like this are solved by iterating over a sequence of integers created by the range function, and then refering to the individual elements of the sequence inside the body of the for loop to perform the desired tasks. The range function accepts one, two or three arguments. With a single integer argument, range returns a sequence of integers from 0 to one less than the argument provided. With two arguments, the first argument is used as a starting value instead of 0, and with three arguments, the third argument is used as an increment instead of the implicit default of 1. Notice that range never includes its upper limit in the returned sequence; like slices (Section 2.4.3), it is designed to work in conjunction with the subscripting of elements in a sequence, which start at 0 and continue to one less than the length of the sequence.

So to zero out all the elements in an array, we could use the range as follows:

>>> x = [1,2,3,4,5]
>>> for i in range(len(x)):
...     x[i] = 0
...
>>> x
[0, 0, 0, 0, 0]
Since the len function returns the number of elements in a sequence, and since subscripts start with 0, range and len work very well together. Here's one solution to the problem of adding together an array of prices and taxes to create a total array:
>>> prices = [12.00,14.00,17.00]
>>> taxes = [0.48,0.56,0.68]
>>> total = [] 
>>> for i in range(len(prices)):
...     total.append(prices[i] + taxes[i]) 
...
>>> total
[12.48, 14.56, 17.68]
Alternatively, we could refer to the elements of total with the same subscripts as the corresponding elements of prices and taxes, but we would first have to initialize total to have the correct number of elements:
>>> total = len(prices) * [0]
>>> for i in range(len(prices)):
...     total[i] = prices[i] + taxes[i]
...
>>> total
[12.48, 14.56, 17.68]
The brackets around the 0 are required so that python will create a list with the appropriate number of elements, rather than a scalar (Section 4.3.2).

The range function actually produces a list in memory containing all the elements specified through its arguments. For sequences involving very large numbers, this may consume large amounts of memory. In cases like this, python provides the xrange function. While this function returns an object that behaves just like the list returned by range, the appropriate elements are calculated as needed, rather than actually stored in memory. Since this makes xrange considerably slower than range, you should only resort to xrange when working with a large range of values.


next up previous contents
Next: while loops Up: Programming Previous: for loops   Contents
Phil Spector 2003-11-12