詳解Python中yield產生器的用法

來源:互聯網
上載者:User

標籤:迭代   python   

yield是產生的意思,但是在python中則是作為產生器理解,產生器的用處主要可以迭代,這樣簡化了很多運算模型(還不是很瞭解是如何簡化的)。

yield是一個運算式,是有返回值的.

當一個函數中含有yield時,它不再是一個普通的函數,而是一個產生器.當該函數被調用時不會自動執行,而是暫停,

參考:http://www.aichengxu.com/view/64610 

見第一個例子:

例1:

>>> def mygenerator():...  print ‘start...‘...  yield 5... >>> mygenerator()   //在此處調用,並沒有列印出start...說明存在yield的函數沒有被運行,即暫停<generator object mygenerator at 0xb762502c>>>> mygenerator().next()  //調用next()即可讓函數運行.start...5>>>


如一個函數中出現多個yield則next()會停止在下一個yield前,見例2:

例2:

>>> def mygenerator():...  print ‘start...‘...  yield 5... >>> mygenerator()   //在此處調用,並沒有列印出start...說明存在yield的函數沒有被運行,即暫停<generator object mygenerator at 0xb762502c>>>> mygenerator().next()  //調用next()即可讓函數運行.start...5>>>


為什麼yield 5會輸出5,yield 23會輸出23? 

我們猜測可能是因為yield是運算式,存在返回值.

那麼這是否可以認為yield 5的返回值一定是5嗎?實際上並不是這樣,這個與send函數存在一定的關係,這個函數實質上與next()是相似的,區別是send是傳遞yield運算式的值進去,而next不能傳遞特定的值,只能傳遞None進去,因此可以認為g.next()和g.send(None)是相同的。見例3:

例3:

>>> def fun():...  print ‘start...‘...  m = yield 5...  print m...  print ‘middle...‘...  d = yield 12...  print d...  print ‘end...‘... >>> m = fun()    //建立一個對象>>> m.next()    //會使函數執行到下一個yield前start...5>>> m.send(‘message‘)  //利用send()傳遞值message     //send()傳遞進來的 middle...12>>> m.next()None      //可見next()返回值為空白end...Traceback (most recent call last): File "<stdin>", line 1, in <module>StopIteration


在multiprocess中的使用

python在處理資料的時候,memory-heavy 的資料往往會導致程式沒辦反運行或者運行期間伺服器其他程式效率受到影響。這種情況往往會把資料集合變為通過genertor來遍曆。

但同時如我們所知,generoter看似只能被單進程消費,這樣效率很低。

generator 可以被pool.map消費。

看一下pool.py的源碼。

for i, task in enumerate(taskseq):  ...  try:   put(task)  except IOError:   debug(‘could not put task on queue‘)   break


實際是先將generator全部消費掉放到queue中。然後通過map來並行。這樣是解決了使用map來並行。

但是依然沒有解決佔用記憶體的問題。這裡有兩步佔用記憶體。

第一步是全部消費掉的generator。

第二步並行運算全部data。

解決第一個問題,通過部分消費generator來達到。

解決第二個問題,可以通過imap來達到.

範例程式碼如下:

import multiprocessing as mpimport itertoolsimport timedef g(): for el in xrange(50):  print el  yield elimport osdef f(x): time.sleep(1) print str(os.getpid()) +" "+ str(x) return x * xif __name__ == ‘__main__‘: pool = mp.Pool(processes=4)    # start 4 worker processes go = g() result = [] N = 11 while True:  g2 = pool.imap(f, itertools.islice(go, N))  if g2:   for i in g2:    result.append(i)    time.sleep(1)  else:   break print(result)


ps: 使用注意事項。在produce資料的時候,盡量少做操作,應為即使是map也是單線程的來消費資料。所以盡量把操作放到map中作。這樣才能更好的利用多進程提高效率。 

Python學習教程中心: http://www.aichengxu.com/item/15 

著作權聲明:本文為博主原創文章,未經博主允許不得轉載。

詳解Python中yield產生器的用法

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.