On 20.11.2014 03:06, Steven D'Aprano wrote:
On Thu, Nov 20, 2014 at 03:24:07AM +1100, Chris Angelico wrote:
Without the generator, *only* __next__ has this effect, and that's exactly where it's documented to be.
The documentation states that __next__ raises StopIteration, it doesn't say that *only* __next__ should raise StopIteration.
I trust that we all expect to be able to factor out the raise into a helper function or method, yes? It truly would be surprising if this failed:
class MyIterator: def __iter__(self): return self def __next__(self): return something()
def something(): # Toy helper function. if random.random() < 0.5: return "Spam!" raise StopIteration
Now let's write this as a generator:
def gen(): while True: yield something()
which is much nicer than:
def gen(): while True: try: yield something() except StopIteration: return # converted by Python into raise StopIteration
I find this example a compelling argument against the PEP. Personally, I'm dealing a lot more often with refactoring a generator function into a iterator class than I'm rewriting generator expressions into comprehensions (at least the exotic kinds that would reveal their inequality). So for me at least, the burden of having to remember that I can let (and should let) StopIteration bubble up inside __next__, but not in generator functions weighs in heavier than the equality argument and the protection against hard-to-diagnose (but rarely occurring) bugs in nested generator functions.