Jacob Holm wrote:
This is a valid point. But consider:
1. The delegating generator has no way to stop the subgenerator prematurely when it uses the yield from. So the yield from can only be stopped prematurely by the delegating generator's caller. And then the subgenerator would have to be communicated between the caller to the delegating generator somehow (e.g, passed in as a parameter) so that the caller could continue to use it. (And the subgenerator has to be a generator, not a plain iterator). "...subgenerator has to be a generator" is not entirely true. For example, if the subiterator doesn't have send, you can send a non-None value to the generator and that will raise an AttributeError at the yield from. If it doesn't have throw, you can even throw a StopIteration with a value to get that value as the result of the yield-from expression, which might be useful in a twisted sort of way. In both cases, the subiterator will only be closed if the yield-from expression actually closes it. So it is definitely possible to get a non-generator prematurely finalized. But non-generators don't have a close (or throw) method. They lack the concept of "finalization". Only generators have these extra methods. So using a subiterator in yield from isn't an issue here. (Or am I missing something)? Well, if the subiterator is a generator that itself uses yield-from,
Bruce Frederiksen wrote: the need to wrap it would destroy all possible speed benefits of using yield-from. So if there *is* a valid use case for yielding from a shared generator, this is not really a solution unless you don't care about speed. Yes, there is a performance penalty in this case. If the wrapper were written in C, then I would think that the penalty would be negligible. Perhaps offer a C wrapper in a standard library?? Note that with explicit close, my argument for special-casing GeneratorExit by adding "except GeneratorExit: raise" weakens. The GeneratorExit will be delegated to the deepest generator/iterator with a throw method. As long as the iterators don't swallow the exception, they will be closed from the finally clause in the expansion. If one of them *does* swallow the exception, the outermost generator will raise a RuntimeError. Another case where close differs from throw(GeneratorExit). Close is define in PEP 342 to raise RuntimeError if GeneratorExit is swallowed. Should the delegating generator, then, be calling close rather throw for GeneratorExit so that the RuntimeError is raised closer to cause of the exception? Or does this violate the "inlining" goal of the current PEP?
-bruce frederiksen