the list, you just need to know that the variable is set to one item after another in the list.
But sometimes you do have to know the index. For example, in geometry a vector (e.g. x,
y and z axis values to specify a position in three-dimensional space) can be implemented
in Python as a list of floating point numbers. Suppose that you wanted to calculate the
Here the calculation for the inner product is (4×1) + (7×3) + (0×5) yielding 25. We
could also save writing out the whole calculation and use a loop to go through all of the
required vector positions (indices) adding the product for each. Thus, instead we can
This is a good enough way of calculating the inner product if you know you are in three
dimensions, i.e. where the length of the vectors is not known beforehand. In this case the
list of indices needs to match the size of the vectors. We can obtain such a list using
The range() function takes one, two or three integer arguments. If it has one argument,
n, then it generates a number sequence starting at 0 and finishing at n-1, in steps of 1. If it
range(2, 7) # [2, 3, 4, 5, 6]
If it has three arguments then the first two, n1 and n2, are as before, and the third is the
step size. There is one subtlety, however: if the step size is positive then the list stops at
the greatest integer less than n2 (which might not be n2-1) and if the step size is negative
then the sequence stops at the least integer greater than n2. If you use a step size of 0 you
get an error.
range(2, 13, 3) # [2, 5, 8, 11]
range(7, 2, -2) # [7, 5, 3]
Returning to the inner product calculation, we simply need to use the length of one of
the vectors len(vec1) to get the required range of indices:
s = 0
for i in range(len(vec1)):
s += vec1[i] * vec2[i]
Here len(vec1) gives the length of vec1 and so range(len(vec1)) gives a list which
exactly contains the valid (non-negative) indices for vec1 and vec2. Note, the code
assumes that vec1 and vec2 are the same length, and that is something that should really
be checked somewhere.
In Python 2 there is an alternative for range(), which is xrange(). The difference is that
range() actually creates a whole list of numbers while xrange() does not; it just sets the
relevant loop variable (here, n) to what it should be set to, one after the other. The
difference between range() and xrange() is normally not an issue but could be if the length
were large. In Python 3, xrange() no longer exists and range() behaves like the Python 2
xrange().
There is another, arguably neater, way we could get at the indices and that is using the
inbuilt enumerate() function, which gives both an index and the corresponding item.
Specifically, it sets the loop variable to a two-tuple whose first item is the index and the
second is the list item at that index:
s = 0
for i, x in enumerate(vec1):
s += x * vec2[i]
It behaves like Python 3’s xrange() in regard to not actually creating one big list (in this
case of 2-tuples), so is reasonably efficient. It might seem possible to also use the .index()
function to get the position of an item in the vector. However, this would only work if
each term in vec1 was unique, and there is no guarantee of that:
s = 0
for x in vec1:
i = vec1.index(x) # bad idea due to repeats
s += vec1[i] * vec2[i]
Also, getting the index in this way is relatively slow. So overall it is much better to stick
with the range() or enumerate() functions.