On Thu, Nov 20, 2014 at 9:46 AM, Terry Reedy email@example.com wrote:
On 11/19/2014 11:24 AM, Chris Angelico wrote:
The distinction in __next__ is between returning something and raising something. The distinction in a generator is between "yield" and "return".
Which, as I said a week ago, is why there is no need for "raise StopIteration" in a generator function. The doc clearly states the limited intended use of StopIteration. ''' exception StopIteration Raised by built-in function next() and an iterator‘s __next__() method to signal that there are no further items produced by the iterator. ''' StopIteration is exposed so it can be raised in user coded __next__() and caught when using explicit next(). If it was only used for builtins and for loops, it would not need to be visible.
Why should a generator author have to be concerned about one particular exception having magical meaning?
I am not sure of your intent with this rhetorical (?) question.
Yes, rhetorical. Basically saying the same as you are: that StopIteration is a part of __next__, not generators.
Imagine this scenario:
def producer(): """Return user input, or raise KeyboardInterrupt""" return input("Enter the next string: ")
The prompt should be "Enter the next string or hit ^C to quit: ".
Yeah, the point is about its interaction with the rest of the program, not the human.
def consumer(): """Process the user's input""" while True: try: command = producer() except KeyboardInterrupt: break dispatch(command)
Okay, now let's make a mock producer:
strings = ["do stuff","do more stuff","blah blah"] def mock_producer() if strings: return strings.pop(0) raise KeyboardInterrupt
That's how __next__ works, only with a different exception, and I think people would agree that this is NOT a good use of KeyboardInterrupt.
It is avoidable because the return type of producer is limited to strings. Therefore, producer could (and perhaps should) itself catch KeyboardInterrupt and return None, which is intended for such use. Consumer would then be simplified by replacing 3 lines with "if command is None: break".
Sure it does. But suppose it does some parsing on the string first, and that parsing might return literally any object. The structure of the program is the same, but now it really does need to signal "no more stuff" in some way other than return value.
Just trying to concoct a situation similar to generators/for loops, using a different exception. I'm fairly sure there's no way to make the above system seem truly plausible, because KeyboardInterrupt is a bad exception for the purpose; but it's still broadly similar, and I think the same applies: StopException should be *only* inside __next__() and next(). Since generators can distinguish yield from return, they don't need to distinguish return from raise.