This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author scoder
Recipients Ludovic.Gasc, gvanrossum, lukasz.langa, martin.panter, pitrou, rhettinger, scoder, vstinner, yselivanov
Date 2015-04-26.20:32:05
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1430080326.07.0.575963702571.issue24018@psf.upfronthosting.co.za>
In-reply-to
Content
PEP 342 isn't really conclusive here as it intended to define the protocol based on the de-facto design of a yield-based generator function. Trying to abstract from that poses the question how a class based generator implementation should look like. Specifically, it is not clear in this case what "raise an exception *inside* the generator" even means.

As Antoine pointed out, there definitely has to be more than an Iterator. However, it's not clear that throw() and close() are always required for an implementation. Simple Generators might get away without special error handling and cleanup.

Similarly, a Generator may not allow (or expect) values to be passed in and only make use of close() for cleanup (and potentially also throw()).

So, there seem to be at least three use cases for the Generator protocol here:

1) an Iterator that can accept input values via send()
2) an Iterator that needs to safely do certain cleanup operations after use (throw/close)
3) a complete Generator that accepts input values and cleans up after it

Given that there used to be only one implementation, I think we can assume that a lot of code depends on the complete protocol. Some recipients will certainly be aware of the exact subset of the protocol that the Generator they have in their hands makes use of, but if they don't, they'll just have to assume it supports everything and requires proper cleanup on errors and on termination.

Therefore, I think it's important to cover the complete protocol in the Generator ABC. I also think it's helpful to not require users to override throw() in a subclass, as they might not need it. "Throwing an exception inside of them" might simply not have a meaning for them. If they do need it, however, then the current implementation might help them to properly raise the exception, given that the 3-argument raise statement is no longer available in Py3.

Both reasons (whether you need throw() or not) make me think that it should not be abstract. The same applies to close(), which has a meaningful implementation now that subclasses can make use of in order to avoid having to implement both close() and throw().

And yes, this is about sneaking past generator type checks because most of them are actually *not* there for a reason. Asyncio is just one example.
History
Date User Action Args
2015-04-26 20:32:06scodersetrecipients: + scoder, gvanrossum, rhettinger, pitrou, vstinner, lukasz.langa, Ludovic.Gasc, martin.panter, yselivanov
2015-04-26 20:32:06scodersetmessageid: <1430080326.07.0.575963702571.issue24018@psf.upfronthosting.co.za>
2015-04-26 20:32:06scoderlinkissue24018 messages
2015-04-26 20:32:05scodercreate