Oscar Benjamin wrote:
Before pep 380 filter(lambda x: True, obj) returned an object that was the same kind of iterator as obj (it would yield the same values). Now the "kind of iterator" that obj is depends not only on the values that it yields but also on the value that it returns. Since filter does not pass on the same return value, filter(lambda x: True, obj) is no longer the same kind of iterator as obj.
Something like this has happened before, when the ability to send() values into a generator was added. If you wrap a generator with filter, you likewise don't get the same kind of object -- you don't get the ability to send() things into your filtered generator. So, "provide the same kind of iterator" is not currently part of the contract of these functions.
When writing code like the above that depends on being able to get the value returned from an iterator, it is no longer possible to freely mix utilities like filter, map, zip, itertools.chain with the iterators returned by parse() as they no longer act as transparent wrappers over the underlying iterators (by not propagating the value attached to StopIteration).
In many cases they *can't* act as transparent wrappers with respect to the return value, because there is more than one return value to deal with. There's also the added complication that sometimes not all of the sub-iterators are run to completion -- e.g. izip() stops as soon as one of them reaches the end. -- Greg