On 21.11.2014 12:24, Raymond Hettinger wrote:
On Nov 15, 2014, at 1:29 AM, Chris Angelico <rosuav@gmail.com mailto:rosuav@gmail.com> wrote:
Abstract
This PEP proposes a semantic change to ``StopIteration`` when raised inside a generator, unifying the behaviour of list comprehensions and generator expressions somewhat.
Please let me know if I'm reading the PEP correctly. Does the proposal break all existing code in generators that uses next() to raise StopIteration or that raises StopIteration explicitly?
For example, here is the pure python recipe for itertools.accumulate() show in the docs at https://docs.python.org/3/library/itertools.html#itertool-functions :
def accumulate(iterable, func=operator.add): 'Return running totals' # accumulate([1,2,3,4,5]) --> 1 3 6 10 15 # accumulate([1,2,3,4,5], operator.mul) --> 1 2 6 24 120 it = iter(iterable) total = next(it) yield total for element in it: total = func(total, element) yield total
Or would it break the traditional examples of how to write something like izip() using a generator?
def izip(iterable1, iterable2): it1 = iter(iterable1) it2 = iter(iterable2) while True: v1 = next(it1) v2 = next(it2) yield v1, v2 assert list(izip('ab', 'cde')) == [('a', 'c'), ('b', 'd')] assert list(izip('abc', 'cd')) == [('a', 'c'), ('b', 'd')]
Since I already learnt quite a lot from following this thread: I checked yesterday what the docs have to say about the pure-python equivalent of python3's zip() because I expected it to look like the above izip recipe (making it incompatible with the PEP behavior). However, I found that the given equivalent code is:
def zip(*iterables): # zip('ABCD', 'xy') --> Ax By sentinel = object() iterators = [iter(it) for it in iterables] while iterators: result = [] for it in iterators: elem = next(it, sentinel) if elem is sentinel: return result.append(elem) yield tuple(result)
i.e., there is no unprotected next call in this example.
What surprised me though is that the protection here is done via the default argument of next() while more typically you'd use a try/except clause. So what's the difference between the two ? Specifically, with a default value given will next just catch StopIteration, which you could do less verbosely yourself and/or is there some speed gain from the fact that the Error has to be propagated up one level less ? Is there a guideline when to use try/except vs. next with a default value ?
Thanks, Wolfgang