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]
async defstarted out as syntactic sugar, yes, to make it easier to spot that you have a coroutine (asdef functionname()does not communicate that somewhere in the body there's ayieldoryield from). I'm putting this in the comments because that part of your question is tangental to your actual issue and makes your question borderline too broad. I'd take it out.range()object is not an awaitable.