2017-02-20 38 views
25

我無法理解Python 3.6中引入的異步引入的使用。作爲一個免責聲明,我沒有很多處理Python中異步代碼的經驗。Python異步解析 - 它們是如何工作的?

what's new for 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) 

據我所知,aiter()函數被異步調用,這樣aiter的每次迭代都可以繼續進行,而前一個必須返回(或者這種理解是錯誤的?)。

我不確定的是如何轉化爲這裏的列表理解。結果是否按照它們返回的順序放入列表中?或者在最終名單中是否有有效的「佔位符」,以便每個結果以正確的順序排列在列表中?或者我在想這個錯誤的方式?

此外,有人能夠提供一個真實世界的例子,可以解釋適用的用例和基本力學async這樣的理解?

+0

我很好奇異步生成器。相同或不同的行爲? –

回答

16

你基本上是問一個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)呼叫不是異步的;它阻止。

現在提供async for替換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()弟兄的功能準確等同物,但是這些使用__aiter____anext__而不是__iter____next__。也就是說,異步掛鉤存在相同的功能,但通過前綴a與非異步變體區分開來。

await關鍵字存在的關鍵區別,所以對於每個迭代一個async for循環的產率進行控制,從而其他協程可以代替運行。

再次重申,所有這些都已經添加到Python 3.5中(請參閱PEP 492),Python 3.6中新增的一點是,您也可以在列表理解中使用這樣的循環。並在發生器的表達和設置和字典的理解,就此而言。

最後但並非最不重要的,同一組的變化也使我們能夠在理解的表達部分使用await <expression>,所以:

[await func(i) for i in someiterable] 

現在是可能的。

+0

感謝Martijn的詳細解答。所以'async for'循環的行爲與普通的'for'循環相同,除了循環迭代的控制被傳遞給封裝的協程?我將不得不恰當地檢查協程的使用,但這更有意義。 –

10

據我所知,aiter()函數被異步調用,使aiter每次迭代可以在沒有前一個必然迴歸尚未進行(或這是理解錯了嗎?)。

這種理解是錯誤的。不能並行執行async for循環的迭代。 async for與正常的for循環一樣。

async for的異步部分是它讓代表協程的迭代器await迭代它。它僅用於異步協程中,並且僅用於特殊的異步可執行文件。除此之外,它幾乎就像一個普通的for循環。

+0

謝謝,看來我需要去正確地理解協程,然後纔會圍繞使用'async'來包裝頭部。我讚賞這一更正。 :) –

相關問題