Online Book Reader

Home Category

Learning Python - Mark Lutz [199]

By Root 1408 0
as we march across it, we need to use indexes so we can assign an updated value to each position as we go. The range/len combination can produce the required indexes for us:

>>> L = [1, 2, 3, 4, 5]

>>> for i in range(len(L)): # Add one to each item in L

... L[i] += 1 # Or L[i] = L[i] + 1

...

>>> L

[2, 3, 4, 5, 6]

When coded this way, the list is changed as we proceed through the loop. There is no way to do the same with a simple for x in L:-style loop, because such a loop iterates through actual items, not list positions. But what about the equivalent while loop? Such a loop requires a bit more work on our part, and likely runs more slowly:

>>> i = 0

>>> while i < len(L):

... L[i] += 1

... i += 1

...

>>> L

[3, 4, 5, 6, 7]

Here again, though, the range solution may not be ideal either. A list comprehension expression of the form:

[x+1 for x in L]

would do similar work, albeit without changing the original list in-place (we could assign the expression’s new list object result back to L, but this would not update any other references to the original list). Because this is such a central looping concept, we’ll save a complete exploration of list comprehensions for the next chapter.

Parallel Traversals: zip and map

As we’ve seen, the range built-in allows us to traverse sequences with for in a nonexhaustive fashion. In the same spirit, the built-in zip function allows us to use for loops to visit multiple sequences in parallel. In basic operation, zip takes one or more sequences as arguments and returns a series of tuples that pair up parallel items taken from those sequences. For example, suppose we’re working with two lists:

>>> L1 = [1,2,3,4]

>>> L2 = [5,6,7,8]

To combine the items in these lists, we can use zip to create a list of tuple pairs (like range, zip is an iterable object in 3.0, so we must wrap it in a list call to display all its results at once—more on iterators in the next chapter):

>>> zip(L1, L2)

>>> list(zip(L1, L2)) # list() required in 3.0, not 2.6

[(1, 5), (2, 6), (3, 7), (4, 8)]

Such a result may be useful in other contexts as well, but when wedded with the for loop, it supports parallel iterations:

>>> for (x, y) in zip(L1, L2):

... print(x, y, '--', x+y)

...

1 5 -- 6

2 6 -- 8

3 7 -- 10

4 8 -- 12

Here, we step over the result of the zip call—that is, the pairs of items pulled from the two lists. Notice that this for loop again uses the tuple assignment form we met earlier to unpack each tuple in the zip result. The first time through, it’s as though we ran the assignment statement (x, y) = (1, 5).

The net effect is that we scan both L1 and L2 in our loop. We could achieve a similar effect with a while loop that handles indexing manually, but it would require more typing and would likely run more slowly than the for/zip approach.

Strictly speaking, the zip function is more general than this example suggests. For instance, it accepts any type of sequence (really, any iterable object, including files), and it accepts more than two arguments. With three arguments, as in the following example, it builds a list of three-item tuples with items from each sequence, essentially projecting by columns (technically, we get an N-ary tuple for N arguments):

>>> T1, T2, T3 = (1,2,3), (4,5,6), (7,8,9)

>>> T3

(7, 8, 9)

>>> list(zip(T1, T2, T3))

[(1, 4, 7), (2, 5, 8), (3, 6, 9)]

Moreover, zip truncates result tuples at the length of the shortest sequence when the argument lengths differ. In the following, we zip together two strings to pick out characters in parallel, but the result has only as many tuples as the length of the shortest sequence:

>>> S1 = 'abc'

>>> S2 = 'xyz123'

>>>

>>> list(zip(S1, S2))

[('a', 'x'), ('b', 'y'), ('c', 'z')]

map equivalence in Python 2.6

In Python 2.X, the related built-in map function pairs items from sequences in a similar fashion, but it pads shorter sequences with None if the argument lengths differ instead of truncating to the shortest length:

>>> S1 = 'abc'

>>> S2 = 'xyz123'

Return Main Page Previous Page Next Page

®Online Book Reader