小談 python 生成器

生成器:  迭代器的另一種操作,它能幹的事,list也都能幹,只不過在需要處理的序列比較大時,列表解析比較費內存。
生成器表達式: 通列表解析語法,只不過把列表解析的[]換成()


例如:
>>> gen = (x**2 for x in range(5))
>>> gen
<generator object <genexpr> at 0x0000000002FB7B40>
>>> for g in gen:
...   print(g, end='-')
...
0-1-4-9-16-
>>> for x in [0,1,2,3,4,5]:
...   print(x, end='-')
...
0-1-2-3-4-5-

生成器函數:  在函數中如果出現了yield 關鍵字,稱這個函數爲生成器函數
def odd():
n=1
while True:
yield n
n+=2
odd_num = odd()
count = 0
for o in odd_num:
if count >=5: break
print(o)
count +=1
 
生成器是包含有__iter()和next__()方法的,所以可以直接使用for來迭代,迭代到最後會返回StopIteration前提是沒return  當然了 return 也不會返回值
其實相當於分解一個迭代器,分解的條件是 yield 直到被 return 或者 StopIteration 當談論 如果在return後返回一個值,
那麼這個值爲StopIteration異常的說明,不是程序的返回值。 生成器是沒有辦法返回值的。
 如
 def test():
    yield 'a'
    yield 'b'
    return 'd'
    yield 'abc'


tt = test()
print(next(tt))  這是定義大a
print(next(tt))  這是定義到b  後面有return 就不走 




生成器的一些方法:
close()  主動關閉生成器,後面的next 都是 StopIteration  通過 調用生成器返回的對象.close() 來實現
send() 接受外部的變量傳入   這是生成器函數最難理解的地方,也是最重要的地方,實現後面的協程就全靠它了
如:
def gen():
value=0
while True:
receive=yield value
print('參數值 =  ',receive)
if receive=='e':
break
value = 'got: %s' % receive


g=gen()
print(g.send(None))
print(g.send('aaa'))
print(g.send(3))
print(g.send('e'))


通過g.send(None)或者next(g)可以啓動生成器函數,並執行到第一個yield語句結束的位置。
此時,執行完了yield語句,但是沒有給receive賦值。
yield value會輸出初始值0
注意:在啓動生成器函數時只能send(None),如果試圖輸入其它的值都會得到錯誤提示信息。
通過g.send('aaa'),會傳入aaa,並賦值給receive,然後計算出value的值,並回到while頭部,執行yield value語句有停止。
此時yield value會輸出"got: aaa",然後掛起。
通過g.send(3),會重複第2步,最後輸出結果爲"got: 3"
當我們g.send('e')時,程序會執行break然後推出循環,最後整個函數執行完畢,所以會得到StopIteration異常。
最後的執行結果如下:


0
got: aaa
got: 3
Traceback (most recent call last):
File "h.py", line 14, in <module>
 print(g.send('e'))
StopIteration






出自:http://www.cnblogs.com/jessonluo/p/4732565.html





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