"7stud" <[EMAIL PROTECTED]> wrote in message news:[EMAIL PROTECTED] | On Apr 18, 8:38 pm, "Terry Reedy" <[EMAIL PROTECTED]> 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 -- http://mail.python.org/mailman/listinfo/python-list