Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between `return iterator` and `yield from iterator`

I'm trying to implement my own version of itertools.compress, the problem is that i stumbled upon the return type. I mean both of these functions return an iterator, but i think the second one is not considered a generator function because there is no yield statement inside. So my question is, are these two implementations equivalent ?

def compress (seq, selectors):
    from operator import itemgetter
    fst = itemgetter (0)
    snd = itemgetter (1)
    yield from map (fst, filter (snd, zip (seq, selectors)))

def compress (seq, selectors):
    from operator import itemgetter
    fst = itemgetter (0)
    snd = itemgetter (1)
    return map (fst, filter (snd, zip (seq, selectors)))
like image 362
marsouf Avatar asked Dec 14 '22 21:12

marsouf


2 Answers

Not quite.

yield from seq is equivalent to for i in seq: yield i

This means your first implementation is a generator that yields each item from the result of map(), while your second implementation returns the map object.

like image 61
avayert Avatar answered Dec 16 '22 09:12

avayert


So my question is, are these two implementations equivalent ?

Your two implementations are not technically equivalent, since they both return different kinds of iterator objects, but they are functionality equivalent, since the resulting objects they return will behave the same as an itertools.compress object.

yield from and return are two different syntactic constructs and thus technically have two different semantic meanings:

yield from <iter> is equivalent to for element in <iter>: yield element, which means when you call your function, it will return a generator, so each subsequent next call on the generator will yield another element from <iter>.

return <expr> on the other hand, will simply return the <expr> object, unchanged, and the function execution will end at the return statement.

In your case, both are actually functionally equivalent to itertools.compress, since in the first case a generator object is returned, which is functionally equivalent to an itertools.compress object, and in the second case a map iterator is returned, which is also functionally equivalent to an itertools.compress object.

So either option, purely functionally speaking would work as custom implementations of itertools.compress. In terms of clarity and conciseness, I would prefer the second version, as the yield from is superfluous, and you get the same functionality just by returning the map iterator itself.

like image 35
Christian Dean Avatar answered Dec 16 '22 10:12

Christian Dean