问题
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)))
回答1:
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.
回答2:
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
回答3:
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