yield from delegates the full iterator protocol to a sub-iterator
yield from iterable is generator delegation introduced by PEP 380. It does not just loop: it forwards send(), throw(), and close() to the sub-iterator, and the value the sub-iterator returns via StopIteration becomes the value of the yield from expression. A manual for loop over the sub-iterator yields the same items but silently drops all of that: send() values never reach the inner generator, exceptions are not thrown into it, and its return value is lost. So yield from is the correct primitive when you are delegating to a sub-generator, and a for loop is correct when you want to transform each item.
Use yield from for flattening, recursive generator walkers, and any delegation where the inner generator may be sent values or has a meaningful return value.
Use an explicit for loop with yield when you need to inspect, filter, or transform each item, or when you want to instrument the flow.
Trade-off: yield from makes the delegation opaque, which is great for correctness and bad for per-item logging or profiling.
Common mistake: writing a for loop wrapper around a coroutine-style generator and expecting send() to work through it. It will not.
Common mistake: assuming yield from accepts any iterable for send purposes; delegation only forwards send/throw when the sub-iterator supports them.
Version note: yield from arrived in Python 3.3 (PEP 380). It is a SyntaxError inside async def functions and async generators, where await and async for are the equivalents.
0-2 years experience
2-5 years experience
5-8 years experience
8+ years experience