What makes an iterator an iterator?
Terry Reedy
tjreedy at udel.edu
Thu Apr 19 16:37:02 EDT 2007
"7stud" <bbxx789_05ss at yahoo.com> wrote in message
news:1176961515.450458.189530 at p77g2000hsh.googlegroups.com...
| On Apr 18, 8:38 pm, "Terry Reedy" <tjre... at udel.edu> wrote:
| >
| > One very good way to get an iterator from an iterable is for .__iter__
to
| > be a generator function.
|
| Ahhh. That eliminates having to deal with next().next constructs.
There never was any 'having' to deal with such a thing. I suggest
completely forgetting .next().next and variants.
| Nice.
|
| > snip all examples of bad code that violate the iterator rule
| > by improperly writing .next as a generator function
|
| What iterator rule states that .next can't be a generator function?
How about the programming rule that a function should return what you want
it to return, or at least something 'close'?
I gave the iterator rule in brief at the top of my posting, but here is
again with several more words: the next method of an iterator for an actual
or virtual collection has no input other than self (and internally stored
information). Each time it is called, its output is either 'another'
object in the collection, if there is at least one, or a StopIteration
exception. For sequences, 'another' most be the next item after the last
one returned (if any). Whether or not duplicates are allowed depends on
the collection type.
Each call of a generator function returns a new generator object. It never
raises StopIteration. So making .next a generator function defines the
collection as an infinite virtual collection (sequence or multiset) of
generators. If that is what is intended (which it is not in the examples
posted), fine. Otherwise, it is a mistake.
| My book says an iterator is any object with a .next method that is
| callable without arguments (Python in a Nutshell(p.65) says the same
| thing).
A complete interface specification specifies information flows in both
directions, as I did before and again here.
| I've read recommendations that an iterator should additionally contain
| an __iter__() method, but I'm not sure why that is. In particular PEP
| 234 says: [snip] should [snip]
In my view, the 'should' should be taken strongly, so that the iterator is
also an iterable. It is certainly idiomatic to follow the advice. Then one
can write code like
def f(iterable):
iterator = iter(iterable)
instead of
def f(iterable):
try: iterator = iter(iterable)
except AttributeError: pass
Terry Jan Reedy
More information about the Python-list
mailing list