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)))
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.
While they may look like very similar, even outputted with results, they are not equivalent.
Look at these basic code examples, mapping str
to range(100)
def do_yield_from():
yield from map(str, range(100))
def do_return():
return map(str, range(100))
print(do_yield_from())
print(do_return())
>>> <class 'generator'>
>>> <class 'map'>
The first function is a generator
, yielding the results from do_yield_from
and a shortened version of
for r in range(100): yield str(r)
The second function returns an instance of map
, which is an iterator
and not a generator
.
Due to the first function being a generator
, yield from
has better performance than do_return
import timeit
print(timeit.timeit(do_yield_from))
>>> 0.53931242968009
print(timeit.timeit(do_return))
>>> 1.467075402143485
So my question is, are these two implementations equivalent ?
Not at all.
yield from
and return
are two different, distinct syntactic constructs.
yield from
is syntax that was introduced in PEP380. It's called generator delegation. From the documentation:
PEP 380 adds the
yield from
expression, allowing a generator to delegate part of its operations to another generator. This allows a section of code containing yield to be factored out and placed in another generator. Additionally, the subgenerator is allowed to return with a value, and the value is made available to the delegating generator.
return
however has completely different behavior. From the documentation:
return may only occur syntactically nested in a function definition, not within a nested class definition.
If an expression list is present, it is evaluated, else None is substituted.
return leaves the current function call with the expression list (or
None
) as return value.
Basically yield from <iter>
is equivlent to for element in <iter>: yield element
, while return
will simply return a single value.
In your case, I believe yield from
is what you're looking for. You want to yield
the values from the map
iterator, not return
the iterator itself.
来源:https://stackoverflow.com/questions/45620608/difference-between-return-iterator-and-yield-from-iterator