Online Book Reader

Home Category

Learning Python - Mark Lutz [204]

By Root 1877 0
call last):

...more omitted...

StopIteration

This initial step is not required for files, because a file object is its own iterator. That is, files have their own __next__ method and so do not need to return a different object that does:

>>> f = open('script1.py')

>>> iter(f) is f

True

>>> f.__next__()

'import sys\n'

Lists, and many other built-in objects, are not their own iterators because they support multiple open iterations. For such objects, we must call iter to start iterating:

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

>>> iter(L) is L

False

>>> L.__next__()

AttributeError: 'list' object has no attribute '__next__'

>>> I = iter(L)

>>> I.__next__()

1

>>> next(I) # Same as I.__next__()

2

Although Python iteration tools call these functions automatically, we can use them to apply the iteration protocol manually, too. The following interaction demonstrates the equivalence between automatic and manual iteration:[34]

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

>>>

>>> for X in L: # Automatic iteration

... print(X ** 2, end=' ') # Obtains iter, calls __next__, catches exceptions

...

1 4 9

>>> I = iter(L) # Manual iteration: what for loops usually do

>>> while True:

... try: # try statement catches exceptions

... X = next(I) # Or call I.__next__

... except StopIteration:

... break

... print(X ** 2, end=' ')

...

1 4 9

To understand this code, you need to know that try statements run an action and catch exceptions that occur while the action runs (we’ll explore exceptions in depth in Part VII). I should also note that for loops and other iteration contexts can sometimes work differently for user-defined classes, repeatedly indexing an object instead of running the iteration protocol. We’ll defer that story until we study class operator overloading in Chapter 29.

* * *

Note


Version skew note: In Python 2.6, the iteration method is named X.next() instead of X.__next__(). For portability, the next(X) built-in function is available in Python 2.6 too (but not earlier), and calls 2.6’s X.next() instead of 3.0’s X.__next__(). Iteration works the same in 2.6 in all other ways, though; simply use X.next() or next(X) for manual iterations, instead of 3.0’s X.__next__(). Prior to 2.6, use manual X.next() calls instead of next(X).

* * *

Other Built-in Type Iterators

Besides files and physical sequences like lists, other types have useful iterators as well. The classic way to step through the keys of a dictionary, for example, is to request its keys list explicitly:

>>> D = {'a':1, 'b':2, 'c':3}

>>> for key in D.keys():

... print(key, D[key])

...

a 1

c 3

b 2

In recent versions of Python, though, dictionaries have an iterator that automatically returns one key at a time in an iteration context:

>>> I = iter(D)

>>> next(I)

'a'

>>> next(I)

'c'

>>> next(I)

'b'

>>> next(I)

Traceback (most recent call last):

...more omitted...

StopIteration

The net effect is that we no longer need to call the keys method to step through dictionary keys—the for loop will use the iteration protocol to grab one key each time through:

>>> for key in D:

... print(key, D[key])

...

a 1

c 3

b 2

We can’t delve into their details here, but other Python object types also support the iterator protocol and thus may be used in for loops too. For instance, shelves (an access-by-key filesystem for Python objects) and the results from os.popen (a tool for reading the output of shell commands) are iterable as well:

>>> import os

>>> P = os.popen('dir')

>>> P.__next__()

' Volume in drive C is SQ004828V03\n'

>>> P.__next__()

' Volume Serial Number is 08BE-3CD4\n'

>>> next(P)

TypeError: _wrap_close object is not an iterator

Notice that popen objects support a P.next() method in Python 2.6. In 3.0, they support the P.__next__() method, but not the next(P) built-in; since the latter is defined to call the former, it’s not clear if this behavior will endure in future releases (as described in an earlier footnote, this appears to be an implementation issue). This is only an issue for manual iteration, though; if you iterate

Return Main Page Previous Page Next Page

®Online Book Reader