[Python-ideas] x=(yield from) confusion [was:Yet another alternative name for yield-from] (original) (raw)

Jacob Holm jh at improva.dk
Mon Apr 6 14:51:53 CEST 2009


Nick Coghlan wrote:

Jacob Holm wrote:

I don't think it is common to keep the generator object alive long after the generator is closed, so I don't see the problem in keeping the value so it can be returned by the next close() call.

I don't think close() means to me what it means to you... close() to me means "I'm done with this, it should have been exhausted already, but just to make sure all the resources held by the internal frame are released properly, I'm shutting it down explicitly" In other words, the normal flow for close() should be the "frame has already terminated, so just return immediately" path, not the "frame hasn't terminated yet, so throw GeneratorExit in and complain if the frame doesn't terminate" path.

That is why #1-6 in my list took care to extract the value from StopIteration and attach it to the generator. Doing it like that allows you to ask for the value after the generator is exhausted normally, using either next() or close(). This is interesting because it allows you to loop over the generator with a normal for-loop and still get the return value after the loop if you want it. (You have to construct the generator before the loop instead of in the for-loop statement itself, and call close() on it afterwards, but that is easy). It also makes it possible for close to reliably return the value.

The idea of saving the value on the generator is more basic than the idea of having close return a value. It means that calling next on an exhausted generator will keep raising StopIteration with the same value. If you don't save the return value on the generator, only the first StopIteration will have a value, the rest will always have None as their value.

You're trying to move throwing GeneratorExit into the internal frame from the exceptional path to the normal path and I don't think that is a good idea.

I think it is exacltly the right thing for the use cases I have.
Anything else requires extra support code to get a similar api. (Extra exceptions to throw in and/or out, an alternative close function to catch the extra exceptions, probably other things as well).

Whether or not it is a good idea to use GeneratorExit for this, I think it is important that a "return value from GeneratorExit" does not silently throw away the value. In other words, if close does not return the value it gets from StopIteration, it should raise an exception if that value is not None.

One option is to let close() reraise the StopIteration if it has a non-None value. This matches Guidos suggestion for a way to access the return value after a GeneratorExit in yield-from without changing his suggested expansion. If the return value from the generator isn't stored and I can't have close() return the value, this would be my preference.

Another option (if you insist that it is an error to return a value after a GeneratorExit) is to let close() raise a RuntimeError when it catches a StopIteration with a non-None value.



More information about the Python-ideas mailing list