use-yield-from / R1737ΒΆ
Message emitted:
Use 'yield from' directly instead of yielding each element one by one
Description:
Yielding directly from the iterator is faster and arguably cleaner code than yielding each element one by one in the loop.
Problematic code:
def bad_yield_from(generator):
for item in generator: # [use-yield-from]
yield item
Correct code:
def good_yield_from(generator):
yield from generator
Additional details:
yield from
can be thought of as removing the intermediary (your for loop) between the function caller and the
requested generator. This enables the caller to directly communicate with the generator (e.g. using send()
).
This communication is not possible when manually yielding each element one by one in a loop.
PEP 380 describes the possibility of adding optimizations specific to yield from
. It looks like they
have not been implemented as of the time of writing. Even without said optimizations, the following snippet shows
that yield from
is marginally faster.
$ python3 -m timeit "def yield_from(): yield from range(100)" "for _ in yield_from(): pass"
100000 loops, best of 5: 2.44 usec per loop
$ python3 -m timeit "def yield_loop():" " for item in range(100): yield item" "for _ in yield_loop(): pass"
100000 loops, best of 5: 2.49 usec per loop
Related links:
Created by the refactoring checker.