2017-10-19 98 views
1

a comment由吉姆·希利亞德Fasarakis:爲什麼基於生成器的協程消耗異步生成器異步數據生成器以及協程異步數據使用者?

發電機:包含一個或多個yield表達式def功能。

生成器用作數據生成器(它們的yield值)。

我能理解。

基於生成器的協程:由types.coroutine包裹的發電機(def + yield)。如果需要將它視爲協程對象,則需要將其包裝在 types.coroutine中。

發電的協同程序作爲消費者(你.send值 他們或子發電機他們yield from)。

什麼是「消費者(你.send值,他們或子發電機他們yield from)」是什麼意思?

異步生成器:async def包含一個或多個yield表達式的函數。這些還可以包含await表達式。

異步生成器是異步數據生成器。

「異步數據生產者」是什麼意思?

協程:async def無零個或多個await S和沒有yield秒。

協同程序是異步數據消費者

什麼是 「異步數據消費者」 是什麼意思?

謝謝。

回答

2

在蟒蛇,發電機在許多不同的方式,現在使用。 生成器的最初目的是暫停執行,然後yield返回一個值給調用者。然後調用者可以稍後調用以恢復發生器。因此發電機是數據生產者。

現在上述版本的生成器只允許通過yield語句返回數據。現在,函數是一個協程,它也應該接受來自調用者的值。因此PEP 342在蟒蛇推出2.5至提升發電機,以便他們可以作爲完全成熟的協同程序。這允許呼叫者向發生器發送值。

現在的新問題是,當生成器被重構,並且您想將其部分操作委託給子生成器時,您需要顯式調用子生成器作爲迭代器,傳播由調用者發送的數據並處理異常。爲了簡化子發生器的操作,在PEP 380中定義了一個新的操作yield from作爲python 3.3的一部分。 yield from在語法上遠不止是簡單的yield語法。在一個完美的世界裏,可能會使用一個新的關鍵字。

現在的問題是,發電機在兩種不同的情況下使用。作爲迭代器和協程。如果一個生成器可以明確定義爲協程,那會更好。因此Python 3.5中的關鍵字爲PEP 492 introduced async and await。因此任何用作協程的發生器都由async關鍵字指示。 Python 3.5中的協程可以使用await關鍵字而不是yield from。請注意,從python 3.5開始,協程是不同的類型!

現在假定您有一個生成器函數defyield。您可以使用裝飾器將現有的發電機類型轉換爲協同型。這些消費者可以通過send()接受價值,並使用yield from將其委託給子發電機。

在python 3.5中,您可以使用async來指示該函數是一個協程類型。這樣的功能可以包含普通的yieldawait。它們不能包含yield from(因爲await取代了該功能)。當協程包含普通的yield時,它們是發生器調用鏈中最低的,因此稱爲異步數據生成器。

沒有簡單yield的任何協程將成爲數據使用者,因爲它必須通過await調用另一個協程才能獲得異步數據。