簡體   English   中英

帶有生成器表達式的 asyncio.gather

[英]asyncio.gather with generator expression

為什么 asyncio.gather 不能與生成器表達式一起使用?

import asyncio

async def func():
    await asyncio.sleep(2)

# Works
async def call3():
    x = (func() for x in range(3))
    await asyncio.gather(*x)

# Doesn't work
async def call3():
    await asyncio.gather(func() for x in range(3))

# Works
async def call3():
    await asyncio.gather(*[func() for x in range(3)])

asyncio.run(call3())

第二種變體給出:

[...]
  File "test.py", line 13, in <genexpr>
    await asyncio.gather(func() for x in range(3))
RuntimeError: Task got bad yield: <coroutine object func at 0x10421dc20>

這是預期的行為嗎?

await asyncio.gather(func() for x in range(3))

這不起作用,因為這將生成器 object作為參數傳遞給gather gather不期望一個可迭代的,它期望協程作為單獨的 arguments。 這意味着您需要打開生成器的包裝。

打開生成器的包裝:

await asyncio.gather(*(func() for i in range(10)))  # star expands generator

我們必須擴展它,因為asyncio.gather需要一個 arguments 列表(即asyncio.gather(coroutine0, coroutine1, coroutine2, coroutine3) ),而不是一個可迭代的

Python 使用* / **用於“解包”和“打包”,具體取決於它是否用於變量賦值。

def foo(*args,**kwargs):...

在這種情況下,所有非關鍵字 args 都被放入一個元組args中,所有 kwargs 都被打包到一個新字典中。 傳入的單個變量仍被打包到元組( * )或字典( ** )中。

這是一種混合

first,*i_take_the_rest,last = range(10)
>>> first=0,i_take_the_rest=[1,2,3,4,5,6,7,8],last=9
*a,b = range(1)
>>> a=[],b=0

但在這里它解包:

combined_iterables = [*range(10),*range(3)]
merged_dict = {**first_dict,**second_dict}

所以基本上,如果它位於等號的左側,或者如果它用於像*foo這樣的函數/方法定義中,它會將內容打包到列表或元組中(分別)。 然而,在理解中,它具有解包行為。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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