python中yield用法詳解

python中yield用法詳解

      今天看python學習視頻學到生成器這一塊時始終弄不懂yield的用法及其原理,在網上詳細查看yield的用法之後總結一下yield的使用方法。

      先看一個簡單的yield語句:

def fib(max):
    n, a, b = 0, 0, 1
    while n < max:
        yield b
        a, b = b, a + b
        n = n + 1

      這是有關斐波那契數列的一個函數,當時正是這個函數中的yield使我困惑導致整個函數不能理解。這個函數包含yield,實際上這已經是一個生成器(generator)了,這與普通的函數有很大的不同。

def h():
    print 'hello'
    yield 6
h()

      可以看到,調用h()之後,print 語句並沒有執行!這就是yield,那麼,如何讓print 語句執行呢?這就是後面要討論的問題,通過後面的討論和學習,就會明白yield的工作原理了。

2. yield是一個表達式

      Python2.5以前,yield是一個語句,但現在2.5中,yield是一個表達式(Expression),比如:

      x = yield 6

表達式(yield 6)的返回值將賦值給x,所以,認爲 x = 6 是錯誤的。那麼如何獲取(yield 6)的返回值呢?需要用到後面要介紹的send(msg)方法。

3. 透過next()語句看原理

      現在,我們來揭曉yield的工作原理。我們知道,我們上面的h()被調用後並沒有執行,因爲它有yield表達式,因此,我們通過next()語句讓它執行。next()語句將恢復Generator執行,並直到下一個yield表達式處。比如:

def h():
    print('hello')
    yield 6
    print('python!')
c = h()
c.__next__()       #這裏是雙下劃線

      c.next()調用後,h()開始執行,直到遇到yield 6,因此輸出結果:

      hello

當我們再次調用c.next()時,會繼續執行,直到找到下一個yield表達式。由於後面沒有yield了,因此會拋出異常:

hello
Traceback (most recent call last):
python!
  File "C:/Users/zxj/PycharmProjects/firstProject/day4/test.py", line 29, in <module>
    c.__next__()
StopIteration

4. send(msg) 與 next()

      瞭解了next()如何讓包含yield的函數執行後,我們再來看另外一個非常重要的函數send(msg)。其實next()和send()在一定意義上作用是相似的,區別是send()可以傳遞yield表達式的值進去,而next()不能傳遞特定的值,只能傳遞None進去。因此,我們可以看做

c.next() 和 c.send(None) 作用是一樣的。

來看這個例子: 

按 Ctrl+C 複製代碼

 

按 Ctrl+C 複製代碼

輸出的結果爲:

hello

ok

      需要提醒的是,第一次調用時,請使用next()語句或是send(None),不能使用send發送一個非None的值,否則會出錯的,因爲沒有yield語句來接收這個值。

5. send(msg) 與 next()的返回值

      send(msg) 和 next()是有返回值的,它們的返回值很特殊,返回的是下一個yield表達式的參數。比如yield 6,則返回 6 。到這裏,是不是明白了一些什麼東西?我們再延續上面的例子:

複製代碼

def h():
    print('hello')
    x = yield 6
    print(m)
    y = yield 23
    print (y)
c = h()
x = c.__next__()  #x 獲取了yield 6 的參數值 6
y = c.send('ok')  #y 獲取了yield 23 的參數值23
print(x,y)

複製代碼

      輸出結果:

hello
ok
6 23

      以上就是python中有關yield用法方面的總結,

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章