More Advanced Coroutines
Learn how to return values in coroutines, and get an introduction to the yield from construction.
Before jumping into the new syntactic capabilities, we need to explore the last jump the coroutines took in terms of their added functionality, in order to bridge missing gaps.
So far, we have a better understanding of coroutines, and we can create simple ones to handle small tasks. We can say that these coroutines are, in fact, just more advanced generators (and that would be right, coroutines are just fancy generators), but, if we actually want to start supporting more complex scenarios, we usually have to go for a design that handles many coroutines concurrently, and that requires more features.
When handling many coroutines, we find new problems. As the control flow of our application becomes more complex, we want to pass values up and down the stack (as well as exceptions), be able to capture values from sub-coroutines we might call at any level, and finally, schedule multiple coroutines to run toward a common goal.
To make things simpler, generators had to be extended once again. That is what PEP-380 addressed by changing the semantics of generators so that they can return values and by introducing the new yield from
construction.
Returning values in coroutines
As introduced before, iteration is a mechanism that calls next()
on an iterable object many times until a StopIteration
exception is raised.
So far, we have been exploring the iterative nature of generators—we produce values one at a time, and, in general, we only care about each value as ...