Online Book Reader

Home Category

Learning Python - Mark Lutz [277]

By Root 1755 0
automatically, and the following iterate manually:

>>> G = (c * 4 for c in 'SPAM')

>>> I = iter(G) # Iterate manually

>>> next(I)

'SSSS'

>>> next(I)

'PPPP'

>>> G = timesfour('spam')

>>> I = iter(G)

>>> next(I)

'ssss'

>>> next(I)

'pppp'

Notice that we make new generators here to iterate again—as explained in the next section, generators are one-shot iterators.

Generators Are Single-Iterator Objects

Both generator functions and generator expressions are their own iterators and thus support just one active iteration—unlike some built-in types, you can’t have multiple iterators of either positioned at different locations in the set of results. For example, using the prior section’s generator expression, a generator’s iterator is the generator itself (in fact, calling iter on a generator is a no-op):

>>> G = (c * 4 for c in 'SPAM')

>>> iter(G) is G # My iterator is myself: G has __next__

True

If you iterate over the results stream manually with multiple iterators, they will all point to the same position:

>>> G = (c * 4 for c in 'SPAM') # Make a new generator

>>> I1 = iter(G) # Iterate manually

>>> next(I1)

'SSSS'

>>> next(I1)

'PPPP'

>>> I2 = iter(G) # Second iterator at same position!

>>> next(I2)

'AAAA'

Moreover, once any iteration runs to completion, all are exhausted—we have to make a new generator to start again:

>>> list(I1) # Collect the rest of I1's items

['MMMM']

>>> next(I2) # Other iterators exhausted too

StopIteration

>>> I3 = iter(G) # Ditto for new iterators

>>> next(I3)

StopIteration

>>> I3 = iter(c * 4 for c in 'SPAM') # New generator to start over

>>> next(I3)

'SSSS'

The same holds true for generator functions—the following def statement-based equivalent supports just one active iterator and is exhausted after one pass:

>>> def timesfour(S):

... for c in S:

... yield c * 4

...

>>> G = timesfour('spam') # Generator functions work the same way

>>> iter(G) is G

True

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

>>> next(I1)

'ssss'

>>> next(I1)

'pppp'

>>> next(I2) # I2 at same position as I1

'aaaa'

This is different from the behavior of some built-in types, which support multiple iterators and passes and reflect their in-place changes in active iterators:

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

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

>>> next(I1)

1

>>> next(I1)

2

>>> next(I2) # Lists support multiple iterators

1

>>> del L[2:] # Changes reflected in iterators

>>> next(I1)

StopIteration

When we begin coding class-based iterators in Part VI, we’ll see that it’s up to us to decide how any iterations we wish to support for our objects, if any.

Emulating zip and map with Iteration Tools

To demonstrate the power of iteration tools in action, let’s turn to some more advanced use case examples. Once you know about list comprehensions, generators, and other iteration tools, it turns out that emulating many of Python’s functional built-ins is both straightforward and instructive.

For example, we’ve already seen how the built-in zip and map functions combine iterables and project functions across them, respectively. With multiple sequence arguments, map projects the function across items taken from each sequence in much the same way that zip pairs them up:

>>> S1 = 'abc'

>>> S2 = 'xyz123'

>>> list(zip(S1, S2)) # zip pairs items from iterables

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

# zip pairs items, truncates at shortest

>>> list(zip([−2, −1, 0, 1, 2])) # Single sequence: 1-ary tuples

[(−2,), (−1,), (0,), (1,), (2,)]

>>> list(zip([1, 2, 3], [2, 3, 4, 5])) # N sequences: N-ary tuples

[(1, 2), (2, 3), (3, 4)]

# map passes paired itenms to a function, truncates

>>> list(map(abs, [−2, −1, 0, 1, 2])) # Single sequence: 1-ary function

[2, 1, 0, 1, 2]

>>> list(map(pow, [1, 2, 3], [2, 3, 4, 5])) # N sequences: N-ary function

[1, 8, 81]

Though they’re being used for different purposes, if you study these examples long enough, you might notice a relationship between zip results and mapped function arguments that our next example can exploit.

Coding

Return Main Page Previous Page Next Page

®Online Book Reader