The following example defines a coroutine multiply
, which waits for a value, multiplies it by a constant factor, and prints the result. Another function, product_table
, uses multiply
to produce product tables.
def multiply(factor):
print(f"product table for {factor}")
while True:
sent_value = yield
result = factor * sent_value
print(f"{factor} x {sent_value} = {result}")
def product_table(coro):
coro.send(None) # start coroutine
for value in range(1, 11):
coro.send(value)
product_table(multiply(3))
running the example produces:
product table for 3
3 x 1 = 3
3 x 2 = 6
3 x 3 = 9
3 x 4 = 12
3 x 5 = 15
3 x 6 = 18
3 x 7 = 21
3 x 8 = 24
3 x 9 = 27
3 x 10 = 30
I am trying to implement the exact same example in terms of async def
and await
, but I'm getting nowhere. My original, incorrect expectation was that the following coroutine function using await
was equivalent to the coroutine relying on yield
:
async def multiply(factor):
print(f"product table for {factor}")
while True:
await sent_value
result = factor * sent_value
print(f"{factor} x {sent_value} = {result}")
It may sound stupid that I expected this to work, but to my dull brain it reads "wait for the sent value". This is not the case -- I get NameError: name 'sent_value' is not defined
.
So far, my limited understanding is that you can define coroutine functions in terms of yield
(as in the first, working example), or in terms of async def
and await
, as I attempted in the second example. This does not seem to be the case.
My concrete questions are:
- How would you implement the first example in terms of
async def
? - Does it even make sense to implement in terms of
async def
?
I hate that all the freaking examples I've found are in terms of fake pipelines that use time.sleep(0.1)
everywhere. I'm trying to make a blog post with examples that use more concrete (if also trivial) pipelines.
[removed erroneous edit]