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用法方面的總結,