詳解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
- python中yield的用法詳解——最簡單,最清晰的解釋Python
- Python yield 用法Python
- Python Yield Generator 詳解Python
- Python中yield的解釋Python
- PHP yield from 生成器用法探究 (二)PHP
- 提高你的Python: 解釋 yield 和 Generators(生成器)Python
- PHP yield 協程 生成器用法探究 (一)PHP
- Python關鍵字yield詳解Python
- Python 關鍵字 yield 詳解Python
- 【Python】迭代器、生成器、yield單執行緒非同步併發實現詳解Python執行緒非同步
- 【python學習筆記】Python生成器yieldPython筆記
- C#中yield return用法分析C#
- Python 生成器原理詳解Python
- Python中enumerate函式用法詳解Python函式
- Python3中*和**運算子的用法詳解!Python
- php-yield生成器PHP
- Python self用法詳解Python
- python yield和yield from用法總結 木槿惜年2013Python
- Python 3 中生成器函式yield表示式的使用Python函式
- Python3中strip()、lstrip()、rstrip()用法詳解Python
- 深入理解python中的yieldPython
- 簡單瞭解一下php的迭代生成器yieldPHP
- STL中set用法詳解
- STL中map用法詳解
- MySQL中BETWEEN子句的用法詳解MySql
- 詳解MySQL中WHERE子句的用法MySql
- Java 中 this 和 super 的用法詳解Java
- Android中的ANR用法詳解Android
- Python迭代和解析(5):搞懂生成器和yield機制Python
- Python3 中 configparser 模組解析配置的用法詳解Python
- Python中dumps, loads dump, load用法詳解Python
- Python中struct.pack()和struct.unpack()用法詳解PythonStruct
- 詳解Vue中watch的高階用法Vue
- oracle中的exists 和not exists 用法詳解Oracle
- java中printf中用法詳解Java
- Java中jar命令用法詳解JavaJAR
- Python | 詳解Python中的協程,為什麼說它的底層是生成器?Python