I've dipped my toes into writing Python code for asynchronous execution, and encountered a lot of new concepts that I felt I need to study up on. One of the keywords I wanted to understand better was "with", which took me to context managers. Another item on the list of mystery was "yield from". I recently learned "yield" in the context of coroutines, and I knew "from" in the context of loading Python modules, but they didn't make sense together. Thankfully I found PEP 380 Syntax for Delegating to a Subgenerator, where my confusion was explained by the fact it had nothing to do with loading modules.

When I read up on coroutines, it took effort for my brain to absorb the concept of code execution interleaved between caller and callee. It was a foreign enough concept my brain didn't flag a consequence of Python's special treatment: the "yield" relationship is limited to one layer of interaction. What if we wanted to refactor a chunk of code, that included a "yield", into another coroutine? Things quickly get messy. If only there's a way to extend yield to multiple levels, and this is the problem PEP 380 wants to solve with "yield from":

The rationale behind most of the semantics presented above stems from the desire to be able to refactor generator code.

Reading through the PEP, I was not happy to see "StopIteration" exception was used to convey a return value out of "yield from". I was taught in the school of "exceptions should be exceptional" and here it is just a normal non-exceptional code return path. My initial reaction was tempered by learning StopIteration is how Python iterators (which are used all the time) signal a halt. I think my instinctive negativity came from experience with languages where exception handling incurs a significant performance overhead. Judging from what I've learned here, either Python exceptions incur no significant penalty or Python designers feel it is an acceptable cost.

For what it's worth, I was not alone in my negative impression. Using StopIteration to convey return value was also disclosed under "Criticisms" sections of PEP 380 and dismissed as "without any concrete justification". Shrug. But I was thankful another criticism was dismissed: looks like there was a suggestion to use syntax of "yield *" and I'm glad it didn't go in that direction because it'd end up as another special syntax very difficult to look up. Searching on * would be a disaster as it is popularly used as a query wildcard character. From this perspective "yield from" is far superior and it only meant typing three more characters. I'm much happier with this approach and I'm glad to see it as I continue my PEP study session with PEP 492.