簡體   English   中英

python:迭代列表或異步生成器

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM