Here is an async function generator by iterating a for
loop. I expected this closure to respect the names from the outer scope.
import asyncio
coroutines = []
for param in (1, 3, 5, 7, 9):
async def coro():
print(param ** 2)
# await some_other_function()
coroutines.append(coro)
# The below code is not async, I made a poor mistake.
# Michael Szczesny's answer fixes this.
for coro in coroutines:
asyncio.run(coro())
While I was expecting the results to be 1, 9, 25, 49, 81
after running, here is the actual output:
81
81
81
81
81
Unexpectedly here, the name param
has taken the same value each time.
Can you explain why this happens and how I can achieve the task of creating lots of async functions in a for
loop with names binding correctly?
The included code does not run asynchronously or uses coro as a closure. Functions are evaluated at runtime in python
. An asynchronous solution would look like this
import asyncio
def create_task(param):
async def coro():
await asyncio.sleep(1) # make async execution noticeable
print(param ** 2)
return coro # return closure capturing param
async def main():
await asyncio.gather(*[create_task(param)() for param in (1,3,5,7,9)])
asyncio.run(main())
Output after 1 second
1
9
25
49
81