簡體   English   中英

生成器中的 python3 send() 函數

[英]python3 send() function in generators

根據docs , send() 函數:

“恢復執行並將一個值“發送”到生成器函數中。value 參數成為當前 yield 表達式的結果。send() 方法返回生成器生成的下一個值,或者如果生成器退出而沒有生成,則引發 StopIteration另一個值。當調用 send() 以啟動生成器時,必須以 None 作為參數調用它,因為沒有可以接收該值的 yield 表達式。

但我不明白,為什么在下面的例子中沒有發生“值參數成為當前產量表達式的結果”:

def gen():
    yield 1
    x = (yield 42)
    print(x)
    yield 2

>>>c=gen() #create generator
>>>next(c) #prints '1' and stop execution, which is caused by yield 1
>>>c.send(100) #prints '42', because 'The send() method returns the next value yielded by the generator'
>>>next(c) #prints 'None' and '2'

那么為什么 x 變量保持“無”,盡管我通過 c.send(100) 向它發送了 100? 看起來,右側的 yield 表達式分兩步工作:首先它將值返回給生成器的調用者,然后它返回生成器內部發送函數的參數。 如果在 send(42) 之前添加額外的 next(c),我會得到預期的行為,並且程序會打印“100”。 從文檔中我不清楚為什么當我調用 send() 時這兩個步驟不應該同時發生。

那么為什么 x 變量保持“無”,盡管我通過 c.send(100) 向它發送了 100?

因為當前的yield不是您認為的那樣,而是之前的yield

當您發送 100 時,生成器仍然在yield 1處停止,而不是在yield 42 ,因此 100 將是yield 1的結果,而不是yield 42

為了更清楚地看到這一點,如果您修改生成器以檢索z變量中yield 1的內容,您將看到z確實包含 100:

>>> def gen():
...     z = yield 1
...     x = (yield 42)
...     print(x, z)
...     yield 2
... 
>>> c=gen()
>>> next(c)
1
>>> c.send(100)
42
>>> next(c)
None 100
2
>>>

這就是為什么額外的next()會打印100 回到你的代碼:

def gen():
    yield 1  # first next(), stops here (before "getting out" of yield)
    x = (yield 42) # second next(), stops here (before "getting out" of yield),
                   # so, when you send(100), then 100 is given to x and execution goes on, so:
    print(x)  # 100 is printed
    yield 2  # ... and 2.

我想我已經想通了。

c = gen()

您在c變量中創建了一個生成器,生成器的任何代碼都不會被執行。

next(c)

然后你使用next()函數, next函數轉到下一個yield語句,這里是yield 1 所以這個yield返回1並停止生成器的執行以嘗試捕獲一個值。

下一行是c.send(100) ,因此yield 1正在等待一個值並且您提供了它,但是這個值沒有被保存。
send方法還執行生成器的其余部分,直到下一個yield語句為:

x = (yield 42)

所以這里的 yield 返回 42 並停止生成器程序以嘗試捕獲一個值。 但在那之后你打電話

next(c)

而且你沒有提供一個值,所以x現在是 None 。 然后執行剩下的代碼(直到下一個yield語句,不要忘記)

print(x)
yield 2

所以它打印x who is None 然后yield返回 2 並嘗試捕獲一個值。

試試寫這個

c = gen()
next(c)
next(c)
c.send(100)

它會起作用(理解為什么!)

來自文檔: value 參數成為當前 yield 表達式的結果。 send() 方法返回生成器產生的下一個值。

假設我們有以下無限生成器:

def infgen():
    a = 0
    while True:
        a = yield a
        a += 1

generato = infgen()

generato.send(None)

輸出:0

.send(None) 的執行與 next() 幾乎相同

現在我們有了 a = 0 的第一個值

代碼停在這里a = yield a

value 成為當前 yield 表達式的結果時

yielded 表達式是yield a 產生expresion的結果

generato.send(5)

.send(5) 我們將 5 發送到一個in 生成器並繼續:

yielded 表達式的結果是a = 5

一 = 5

+= 1

使用 a = 5 + 1 = 6 轉到 while 循環

並停止並產生 a ,其中 a 為 6

輸出:6

暫無
暫無

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

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