[Python-ideas] Possible PEP 380 tweak

Guido van Rossum guido at python.org
Sat Oct 30 05:26:40 CEST 2010

On Fri, Oct 29, 2010 at 8:09 PM, Greg Ewing <greg.ewing at canterbury.ac.nz> wrote:
> Guido van Rossum wrote:
>> This seems to be the crux of your objection. But if I look carefully
>> at the expansion in the current version of PEP 380, I don't think this
>> problem actually happens: If the outer generator catches
>> GeneratorExit, it closes the inner generator (by calling its close
>> method, if it exists) and then re-raises the GeneratorExit:
> Yes, but if you want close() to cause the generator to finish
> normally, you *don't* want that to happen. You would have to
> surround the yield-from call with a try block to catch the
> GeneratorExit,

Yeah, putting such a try-block around yield from works just as it
works around plain yield: it captures the GeneratorExit thrown in. As
a bonus, the inner generator is first closed, but the yield-from
expression which was interrupted is not completed; just like anything
else that raises an exception, execution of the code stops immediately
and resumes at the except block.

> and even then you would lose the return value
> from the inner generator, which you're probably going to
> want.

Really? Can you show a realistic use case? (There was Nick's
average-of-sums example but I think nobody liked it.)

>> Could it be that you are thinking of your accelerated implementation,
> No, not really. The same issues arise either way.


>> It looks to me as if using g.close() to capture the return value of a
>> generator is not of much value when using yield-from, but it can be of
>> value for the simpler pattern that started this thread.
> My concern is that this feature would encourage designing
> generators with APIs that make it difficult to refactor the
> implementation using yield-from later on. Simple things
> don't always stay simple.

Yeah, but there is also YAGNI. We shouldn't plan every simple thing to
become complex; in fact we should expect most simple things to stay
simple. Otherwise you'd never use lists and dicts but start with
classes right away.

>> def summer():
>>  total = 0
>>  try:
>>    while True:
>>      total += yield
>>  except GeneratorExit:
>>    raise StopIteration(total)  ## return total
> I don't see how this gains you much. The generator is about
> as complicated either way.

I'm just concerned about the following:

> The only thing that's simpler is the final step of getting
> the result, which in my version can be taken care of with
> a fairly generic helper function that could be provided
> by the stdlib.

In my case too -- it would just be a method on the generator named close(). :-)

In addition I like merging use cases that have some overlap, if the
non-overlapping parts do not conflict. E.g. I believe the reason we
all ended agreeing (at least last year :-) that returning a value
should be done through StopIteration was that this makes it so that
"return", "return None", "return <value>" and falling of the end of
the block are treated uniformly so that equivalences apply both ways.
In the case of close(), I *like* that the response to close() can be
either cleaning up or returning a value and that close() doesn't care
which of the two you do (and in fact it can't tell the difference).

--Guido van Rossum (python.org/~guido)

More information about the Python-ideas mailing list