Online Book Reader

Home Category

Learning Python - Mark Lutz [211]

By Root 1709 0
especially since range builds result lists there and so is not as efficient in its memory usage. As noted in a sidebar in the prior chapter, the file.xreadlines() method used to minimize memory use in 2.X has been dropped in Python 3.0 for similar reasons, in favor of file iterators.

* * *

The map, zip, and filter Iterators

Like range, the map, zip, and filter built-ins also become iterators in 3.0 to conserve space, rather than producing a result list all at once in memory. All three not only process iterables, as in 2.X, but also return iterable results in 3.0. Unlike range, though, they are their own iterators—after you step through their results once, they are exhausted. In other words, you can’t have multiple iterators on their results that maintain different positions in those results.

Here is the case for the map built-in we met in the prior chapter. As with other iterators, you can force a list with list(...) if you really need one, but the default behavior can save substantial space in memory for large result sets:

>>> M = map(abs, (-1, 0, 1)) # map returns an iterator, not a list

>>> M

>>> next(M) # Use iterator manually: exhausts results

1 # These do not support len() or indexing

>>> next(M)

0

>>> next(M)

1

>>> next(M)

StopIteration

>>> for x in M: print(x) # map iterator is now empty: one pass only

...

>>> M = map(abs, (-1, 0, 1)) # Make a new iterator to scan again

>>> for x in M: print(x) # Iteration contexts auto call next()

...

1

0

1

>>> list(map(abs, (-1, 0, 1))) # Can force a real list if needed

[1, 0, 1]

The zip built-in, introduced in the prior chapter, returns iterators that work the same way:

>>> Z = zip((1, 2, 3), (10, 20, 30)) # zip is the same: a one-pass iterator

>>> Z

>>> list(Z)

[(1, 10), (2, 20), (3, 30)]

>>> for pair in Z: print(pair) # Exhausted after one pass

...

>>> Z = zip((1, 2, 3), (10, 20, 30))

>>> for pair in Z: print(pair) # Iterator used automatically or manually

...

(1, 10)

(2, 20)

(3, 30)

>>> Z = zip((1, 2, 3), (10, 20, 30))

>>> next(Z)

(1, 10)

>>> next(Z)

(2, 20)

The filter built-in, which we’ll study in the next part of this book, is also analogous. It returns items in an iterable for which a passed-in function returns True (as we’ve learned, in Python True includes nonempty objects):

>>> filter(bool, ['spam', '', 'ni'])

>>> list(filter(bool, ['spam', '', 'ni']))

['spam', 'ni']

Like most of the tools discussed in this section, filter both accepts an iterable to process and returns an iterable to generate results in 3.0.

Multiple Versus Single Iterators

It’s interesting to see how the range object differs from the built-ins described in this section—it supports len and indexing, it is not its own iterator (you make one with iter when iterating manually), and it supports multiple iterators over its result that remember their positions independently:

>>> R = range(3) # range allows multiple iterators

>>> next(R)

TypeError: range object is not an iterator

>>> I1 = iter(R)

>>> next(I1)

0

>>> next(I1)

1

>>> I2 = iter(R) # Two iterators on one range

>>> next(I2)

0

>>> next(I1) # I1 is at a different spot than I2

2

By contrast, zip, map, and filter do not support multiple active iterators on the same result:

>>> Z = zip((1, 2, 3), (10, 11, 12))

>>> I1 = iter(Z)

>>> I2 = iter(Z) # Two iterators on one zip

>>> next(I1)

(1, 10)

>>> next(I1)

(2, 11)

>>> next(I2) # I2 is at same spot as I1!

(3, 12)

>>> M = map(abs, (-1, 0, 1)) # Ditto for map (and filter)

>>> I1 = iter(M); I2 = iter(M)

>>> print(next(I1), next(I1), next(I1))

1 0 1

>>> next(I2)

StopIteration

>>> R = range(3) # But range allows many iterators

>>> I1, I2 = iter(R), iter(R)

>>> [next(I1), next(I1), next(I1)]

[0 1 2]

>>> next(I2)

0

When we code our own iterable objects with classes later in the book (Chapter 29), we’ll see that multiple iterators are usually supported by returning new objects for the iter call; a

Return Main Page Previous Page Next Page

®Online Book Reader