Асинхронный итерируемый объект может вызывать асинхронный код в своей реализации __aiter__()
, а асинхронный итератор может вызывать асинхронный код в своем методе __anext__()
.
Асинхронный оператор async for ... in
обеспечивает удобную итерацию по асинхронным итераторам и асинхронным генераторам.
Асинхронный оператор async for ... in
действует только в теле асинхронной функции (сопрограммы) async def
.
async for TARGET in ITER: SUITE else: SUITE2
Семантически эквивалентно:
iter = (ITER) iter = type(iter).__aiter__(iter) running = True while running: try: TARGET = await type(iter).__anext__(iter) except StopAsyncIteration: running = False else: SUITE else: SUITE2
Конечно же, для асинхронного async for
можно использовать короткий синтаксис, который подробно описан в списках-выражениях. Действует только в теле асинхронной функции (сопрограммы) async def
.
# асинхронное выражение-генератор: (i ** 2 async for i in agen()). # асинхронное список-выражение: [i async for i in agen()] # асинхронное словарь-выражение: {i: i ** 2 async for i in agen()} ; # асинхронное выражение-множество: {i async for i in agen()}
Теперь разрешено использование выражений await
как в асинхронном, так и в синхронном понимании коротких выражений генераторов.
# на примере списка-выражения result = [await fun() for fun in funcs] result = [await fun() for fun in funcs if await smth] result = [await fun() async for fun in funcs] result = [await fun() async for fun in funcs if await smth]
import asyncio async def ticker(delay, to): for i in range(to): yield (i, delay) await asyncio.sleep(delay) async def run(k): # пример асинхронного for async for i in ticker(k, 10): print(i) loop = asyncio.get_event_loop() try: loop.run_until_complete(asyncio.gather(run(0.5),run(1))) finally: loop.close() # (0, 0.5) # (0, 1) # (1, 0.5) # (1, 1) # (2, 0.5) # (3, 0.5) # (2, 1) # (4, 0.5) # (5, 0.5) # (3, 1) # (6, 0.5) # (7, 0.5) # (4, 1) # (8, 0.5) # (9, 0.5) # (5, 1) # (6, 1) # (7, 1) # (8, 1) # (9, 1)