On Fri, Oct 29, 2010 at 8:09 PM, Greg Ewing firstname.lastname@example.org 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).