[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