[Python-ideas] x=(yield from) confusion [was:Yet another alternative name for yield-from]
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.
- Jacob
More information about the Python-ideas
mailing list