標籤:擷取資料 __name__ 返回 post time [] main 實現 obj
首先看一下什麼是列表產生式
>>> [i*2 for i in range(10)][0, 2, 4, 6, 8, 10, 12, 14, 16, 18]>>> a=[]>>> for i in range(10):... a.append(i*2)...>>> a[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
這一句代碼就實現了三句代碼的效果,這一句代碼就是列表產生式
列表如果存的資料太多,就會佔用很大的儲存空間
如果只取列表中的一些資料,那麼其它不用的資料佔用的儲存空間就白佔了
產生器也能儲存資料,但是它只記錄當前資料,剩下的資料都還沒產生,這樣就不會佔用太多的儲存空間
怎麼建立一個產生器呢?
>>> [i*2 for i in range(10)][0, 2, 4, 6, 8, 10, 12, 14, 16, 18]>>> (i*2 for i in range(10))<generator object <genexpr> at 0x0000021C9C2E5258>
這樣就是一個產生器了,沒有直接產生資料
要取一個資料就產生一個資料
那麼怎麼擷取產生器裡的資料呢?
>>> b = (i*2 for i in range(10))>>> b<generator object <genexpr> at 0x0000021C9C2E5308>>>> b.__next__()0>>> b.__next__()2>>> b.__next__()4>>> next(b)6>>> next(b)8>>> next(b)10
產生器使用next()方法擷取資料,next(b),這是Python3和Python2通用的方法
Python3中還可以用__next__()方法,b.__next__()
Python2中用next()方法,b.next()
但是用next()方法一次次取資料太麻煩,所以通常都用for迴圈來列印資料
>>> c = (i*2 for i in range(10))>>> for n in c:... print(n)...024681012141618
如果函數裡有yield關鍵字,這個函數就是產生器
# -*- coding:utf-8 -*-__author__ = "MuT6 Sch01aR"def test(n): m = 0 b = 0 while m<n: print("before yield") yield b b = b+3 print("after yield") m =m+1 return "test return"a =test(10)while True: try: b = a.__next__() print("in the next",b) except StopIteration as e: print(e.value) #StopIteration的value為產生器的傳回值 exit()
運行結果
運行過程:
首先是調用test()函數
然後執行while迴圈
到__next__()方法的時候,跳到test()函數
執行完yield後,沒繼續執行下面的語句,而是返回到__next__()方法後的語句
執行完該語句後繼續執行while迴圈,執行__next__()方法
然後又跳轉到yield後的語句
產生器調用next()方法的時候執行,執行到產生器中的yield的時候返回,然後執行next()方法後的語句,再執行到next()方法的時候,就會跳到執行yield的語句,之後執行yield後的語句
用產生器實現單線程多並發
# -*- coding:utf-8 -*-__author__ = "MuT6 Sch01aR"import timedef consumer(name): print(‘%s準備吃包子‘ %name) while True: baozi = yield print(‘%s包子來了,被%s吃了‘ %(baozi,name))def producer(): c = consumer(‘張三‘) c2 = consumer(‘李四‘) c.__next__() c2.__next__() print(‘我開始準備做包子了‘) for i in range(10): time.sleep(1) print(‘我做了2個包子‘) c.send(‘肉‘) #調用yield,並傳值 c2.send(‘菜‘)if __name__ == ‘__main__‘: producer()
send方法不僅可以調用yield,還給yield傳值
運行結果
實現了單線程多並發的效果
Python函數(十一)-產生器