[英]python: iterate over either a list or an async generator
由於迭代器是在 python 中引入的,因此總是可以不關心您是在處理迭代器還是列表:
from random import random
def gen_list():
print('gen')
for i in range(10):
yield i
def return_list():
print('return')
return [i for i in range(10)]
if random() > 0.5:
x = gen_list()
else:
x = return_list()
for i in x:
pass
PEP 492 引入了異步迭代器和async for
語法。 我看不到為異步迭代器的使用者添加語法的新負擔的任何理由。
在我的代碼中,我有時處理一個列表(來自緩存),有時處理一個異步生成器:
import asyncio
from random import random
def is_small_and_in_cache():
if random() > 0.5:
print('in fake cache')
return [i for i in range(10)]
async def get_progressively():
print('gen')
for i in range(10):
# e.g. an await here
await asyncio.sleep(0.1)
yield i
async def main():
x = is_small_and_in_cache()
if x is None:
x = get_progressively()
async for i in x:
pass
asyncio.run(main())
但上述失敗(一半時間) TypeError: 'async for' requires an object with __aiter__ method, got list
。
主要問題:如何寫這個以便我們可以處理任何一個? 我應該嘗試將列表轉換為虛擬異步生成器,還是包裝異步生成器以生成列表?
Side Quest:是否有任何建議可以擺脫(對我來說顯然是非pythonic) async for
構造,即為什么常規for
循環不能處理異步生成器? Python3x 在可用性方面失去了它的方式嗎?
語法的存在是為了警告您,您的“循環”實際上可能包括暫停整個調用,允許其他代碼運行,以便您知道在每次迭代頂部的一致 state 中具有適當的數據。 它不會去任何地方。
當然,協程不必暫停,您可以使用它來包裝任何可迭代的微不足道的東西:
async def desync(it):
for x in it: yield x
這比相反的數字更有用——它仍然是異步的,因為它必須——聚集到一個列表中:
async def gather(ai):
ret=[]
async for x in ai: ret.append(x)
return ret
因為它允許在完全異步的情況下進行適當的交錯。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.