Python生成器next方法和send方法區別

生成器簡介

python中,含有yield關鍵字的對象就是一個生成器,每次調用next方法時會執行到yield後面的語句,而後返回yield後面代碼塊的執行結果。其實也能夠調用send方法
下面給個例子方便理解。html

next方法

def foo():
    bar_a = yield 1         # bar_a是語句塊(yield 1)的返回值,默認爲None
    bar_b = yield bar_a
    yield "最後一個值,再迭代就要報StopIteration了"

f = foo()                   # 建立生成器,此時沒有執行foo()裏的任何語句
print(next(f))              # 從foo()裏進入,一直執行到(yield 1)處,此時變量bar_a尚未建立
print(next(f))              # 先將語句塊(yield 1)的返回值賦值個bar_a,此時bar_a的值是None。
                            # 而後執行到語句塊(yield bar_a),bar_b也尚未被建立
print(next(f)

輸出:python

>>>1
>>>None
>>>最後一個值,再迭代就要報StopIteration了

能夠看出,f = foo()建立生成器時,每次執行到yield時,會跳出去並將yield關鍵字後面的內容返回給調用者。下一次有別的調用者再次調用生成器時,會先恢復生成器上次的機器狀態,再接着執行指導遇到yield或者元素迭代完畢。
並且咱們能夠看到bar_abar_b是語句yield 1yield bar_a的返回值,注意:不是生成器的返回值
這裏有個比較繞的地方,咱們用bar_a = yield 1作分析:express

  • 1是生成器的返回值。由於生成器返回yield後面的代碼塊
  • bar_a是語句yield 1的返回值,這就比如咱們寫函數

    a = print('my lover')
    print('a的值是:', a)

    會輸出:翻譯

    >>>my lover
    >>>a的值是: None

send方法

def foo():
    bar_a = yield 1
    bar_b = yield bar_a
    yield "最後一個值,再迭代就要報StopIteration了"

f = foo()
print(f.send(None))
print(f.send("my lover"))
print(next(f))

輸出:code

>>>1
>>>my lover
>>>最後一個值,再迭代就要報StopIteration了

這裏f.send(None)是初始化生成器,和next(f)的效果如出一轍。可是不推薦這麼寫,由於不規範。
注意輸出的第二行是字符串my lover,而不是None。這是由於send函數帶有一個參數,這個參數會覆蓋yield 1語句的返回值,也就是bar_a的值如今不是None了。htm

FAQ

官網提到,當咱們建立一個生成器時,第一次調用只能用next()或者send(None)。由於此時send傳入其餘參數也沒有yield語句去接收。
這句話我看不懂,說的好像傳入None就有yield來接收似的。各位若是明白的歡迎指點。
原文和傳送門以下:對象

官網傳送門字符串

Resumes the execution and 「sends」 a value into the generator function. The value argument becomes the result of the current yield expression. The send() method returns the next value yielded by the generator, or raises StopIteration if the generator exits without yielding another value. When send() is called to start the generator, it must be called with None as the argument, because there is no yield expression that could receive the value.
Google翻譯版本:
恢復執行並將值「發送」到生成器函數中。所述 值參數成爲當前產量表達的結果。該 send()方法返回由生成器產生的下一個值,或者StopIteration若是生成器退出而不產生另外一個值則引起。當send()調用啓動生成器時,必須將其None做爲參數調用,由於沒有能夠接收該值的yield表達式。

更新:
2018-11-24
對生成器使用send(None)方法,解釋器在底層會調用__next__方法,也就是next()方法get

相關文章
相關標籤/搜索