Python 3.6。で説明されている非同期内包表記の使用を理解するのに問題があります。免責事項として、Pythonで一般的に非同期コードを扱う経験はあまりありません。
Python 3.6 ドキュメントの新機能は次のとおりです。
_result = [i async for i in aiter() if i % 2]
_
[〜#〜] pep [〜#〜] では、これは次のように展開されます。
_result = []
async for i in aiter():
if i % 2:
result.append(i)
_
Ithinkaiter()
関数が非同期に呼び出されるため、aiter
の各反復が前のものは必然的にまだ戻っています(または、この理解は間違っていますか?)。
私がわからないのは、それがどのようにここでリストの理解に変換されるかということです。結果は返される順にリストに入れられますか?または、各結果が正しい順序でリストに配置されるように、最終リストに効果的な「プレースホルダー」がありますか?または、私はこれについて間違った方法で考えていますか?
さらに、誰かが、このような理解での適用可能なユースケースとasync
の基本的な仕組みの両方を示す実世界の例を提供できますか?
基本的に、通常のループで_async for
_ループがどのように機能するかを尋ねています。リスト内包表記でこのようなループを使用できるようになったからといって、ここでは何の違いもありません。これは、通常のリスト内包表記とまったく同じように、繰り返しlist.append()
呼び出しを避ける最適化です。
その後、_async for
_ループは、通常のfor
ループがブロックする反復プロトコルの次の各ステップを単に待機します。
説明のために、通常のfor
ループを想像してください:
_for foo in bar:
...
_
このループでは、Pythonが本質的にこれを行います。
_bar_iter = iter(bar)
while True:
try:
foo = next(bar_iter)
except StopIteration:
break
...
_
next(bar_iter)
呼び出しは非同期ではありません。ブロックします。
for
を_async for
_に置き換え、Pythonの変更点:
_bar_iter = aiter(bar) # aiter doesn't exist, but see below
while True:
try:
foo = await anext(bar_iter) # anext doesn't exist, but see below
except StopIteration:
break
...
_
上記の例では、aiter()
とanext()
は架空の関数です。これらはiter()
およびnext()
の機能的に完全に同等ですが、___iter__
_および___next__
_の代わりに___aiter__
_および___anext__
_を使用します。つまり、同じ機能用の非同期フックが存在しますが、接頭辞a
によって非同期フックとは区別されます。
await
キーワードには重大な違いがあるため、反復ごとに_async for
_ループが制御を生成するため、代わりに他のコルーチンを実行できます。
繰り返しになりますが、これはすべてPython 3.5で既に追加されています( PEP 492 を参照)。Python 3.6の新しい点は、リスト内包表記でもこのようなループを使用できます。また、ジェネレーター式およびセットおよびディクテーションの理解では、その点についてです。
最後になりましたが、同じ一連の変更により、内包表記の式セクションで_await <expression>
_を使用できるようになりました。
_[await func(i) for i in someiterable]
_
今は可能です。
I 思考
aiter()
関数が非同期に呼び出されることを理解しているため、aiter
の各反復は、前の反復がまだ戻ることなく続行できます(または、この理解は違う?)。
その理解は間違っています。 async for
ループの反復は並行して実行できません。 async for
は、通常のfor
ループと同様にシーケンシャルです。
async for
の非同期部分は、コルーチンの代わりにイテレータawait
を反復させることです。これは、非同期コルーチン内で使用するためのものであり、特別な非同期イテラブルでのみ使用するためのものです。それ以外は、ほとんどが通常のfor
ループのようです。