Greg Ewing wrote:
We have a decision to make. It appears we can have *one* of the following, but not both:
(1) In non-refcounting implementations, subiterators are finalized promptly when the delegating generator is explicitly closed.
(2) Subiterators are not prematurely finalized when other references to them exist.
Since in the majority of intended use cases the subiterator won't be shared, (1) seems like the more important guarantee to uphold. Does anyone disagree with that?
If you choose (2), then (1) is trivial to implement in code that uses the new expression in combination with existing support for deterministic finalisation. For example: with contextlib.closing(make_subiter()) as subiter: yield from subiter On the other hand, if you choose (1), then it is impossible to use that construct in combination with any other existing constructs to avoid finalisation - you have to write out the equivalent code from the PEP by hand, leaving out the finalisation parts. So I think dropping the implicit finalisation is the better option - it simplifies the new construct, and plays well with explicit finalisation when that is what people want. However, I would also recommend *not* special casing GeneratorExit in that case: just pass it down using throw. Note that non-generator iterators that want "throw" to mean the same thing as "close" can do that easily enough: def throw(self, *args): self.close() reraise(*args) (reraise itself would just do the dance to check how many arguments there were and use the appropriate form of "raise" to reraise the exception) Hmm, that does suggest another issue with the PEP however: it only calls the subiterator's throw with the value of the thrown in exception. It should be using the 3 argument form to avoid losing any passed in traceback information. Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia ---------------------------------------------------------------