때로는 한 줄에 비동기 제너레이터를 만들고 싶을 때가 있다. Python 라이브러리는 Python 라이브러리에서 오랫동안 제공되었던 제너레이터 컴프리헨션과 비동기 유사체인 비동기 제너레이터 컴프리헨션의 형태로 이를 위해 사용할 수 있는 또 다른 shorthand를 제공한다.
it = (<async_expression> async for <variable> in <async_iterable> if <condition>)
async def _gen():
async for <variable> in <async_iterable>:
if <condition>:
yield <async_expression>
it = _gen()
필요하지 않다면 if <condition>
절을 생략할 수 있다. 하나의 비동기 제너레이터를 사용하여 한 줄의 코드로 다른 비동기 제너레이터를 만들 수 있다. 또한 <async_expression>
, <async_iterable>
및 <condition>
은 비동기 제너레이터의 본문에 포함되므로 비동기 코드를 포함할 수 있지만 statement 자체는 실제로 비동기 코드를 실행하지 않는다.
def sync_method(gen):
# This is a synchronous method
...
it = (
await x.run()
async for x in gen
if not (await x.skip())
)
...
return it
일반적으로 허용되지 않는 동기 메소드에 await
문을 포함하는 것처럼 보이지만 유효하다.
더 많은 혼란을 피하기 위해 동기코드를 사용하지 않는 비동기 컴프리헨션 the asynchronous list comprehension이 있다.
asynchronous list comprehension(코루틴 메서드의 본문과 같이 비동기식 코드가 허용되는 컨텍스트에서만 다시 나타날 수 있음)의 기본 형식은 다음과 같다.
l = [<async_expression> async for <variable> in <async_iterable> if <condition>]
async def _list():
r = []
async for <variable> in <async_iterable>:
if <condition>:
l.append(<async_expression>)
return r
l = await _list()
제너레이터 버전과 미묘하게 다르다. 이 경우 묵시적으로 async def
를 사용하여 코루틴 함수로 만든 다음 호출 하고 awaited한다. 이는 컴프리헨션이 배치되고 있는 context에서 발생하기 때문에 컴프리헨션은 await
가 유효한 context에서만 사용할 수 있는것을 의미한다.