詳解Python中yield生成器的用法
http://blog.csdn.net/hello_katty/article/details/47310843
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 mp
- import itertools
- import time
- def g():
- for el in xrange(50):
- print el
- yield el
- import os
- def f(x):
- time.sleep(1)
- print str(os.getpid()) +" "+ str(x)
- return x * x
- if __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的用法詳解——最簡單,最清晰的解釋Python
- PHP yield from 生成器用法探究 (二)PHP
- PHP yield 協程 生成器用法探究 (一)PHP
- python yield和yield from用法總結 木槿惜年2013Python
- Python中dumps, loads dump, load用法詳解Python
- Python self用法詳解Python
- Python3中*和**運算子的用法詳解!Python
- Python3中strip()、lstrip()、rstrip()用法詳解Python
- php-yield生成器PHP
- Python3 中 configparser 模組解析配置的用法詳解Python
- Python學習筆記-yield用法及優點Python筆記
- 深入理解python中的yieldPython
- MySQL中BETWEEN子句的用法詳解MySql
- 詳解MySQL中WHERE子句的用法MySql
- Java 中 this 和 super 的用法詳解Java
- 生成器yield,next()與send()
- 簡單瞭解一下php的迭代生成器yieldPHP
- Python迭代和解析(5):搞懂生成器和yield機制Python
- Python | 詳解Python中的協程,為什麼說它的底層是生成器?Python
- 使用python來操作redis用法詳解PythonRedis
- python使用迭代生成器yield減少記憶體佔用的方法Python記憶體
- 詳解Vue中watch的高階用法Vue
- 詳解Go regexp包中 ReplaceAllString 的用法Go
- lambda+yield+生成器+迭代器
- java中printf中用法詳解Java
- AngularJS select中ngOptions用法詳解AngularJSGo
- axios的用法詳解iOS
- Python3中的列表生成式、生成器與迭代器例項詳解Python
- Python中 sys.argv[]的用法解釋Python
- Python中的列表詳解Python
- 詳解Python中的程式Python
- Python中的Super詳解Python
- c# yield關鍵字原理詳解C#
- ES6中Promise用法詳解Promise
- PHP yield 高階用法——網路PHP
- Python中可迭代物件、迭代器以及iter()函式的兩個用法詳解Python物件函式
- PHP效能優化:生成器 yield的初體驗PHP優化
- Python區域性函式及用法詳解Python函式
- struct的匿名用法詳解Struct