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.