要想理解yield
, 須要先理解generators
(生成器), 要想理解generators
, 須要先理解iterables(迭代器)python
先看這段代碼:code
>>> mylist = [1, 2, 3] >>> for i in mylist: ... print(i) 1 2 3 >>> mylist2 = [x for x in range(3)] >>> for i in mylist2: ... print i ... 0 1 2
這段代碼的意思是list(列表)在python中是能夠迭代的, 若是你須要一個接一個的訪問一個數據集合, 大多數的時候使用一個for xx in yy
這種方式, 那麼這裏的yy
就是一個能夠迭代訪問的數據集合, 很明顯, list
, tuple
, string
, file
這些都是迭代器內存
iterables
是保存在內存中的, 你能夠隨便訪問他們, 好比上面的mylist
,mylist2
get
再看這一段generator
>>> mygenerator = (x*x for x in range(3)) >>> for i in mygenerator: ... print(i) 0 1 4 >>> mygenerator <generator object <genexpr> at 0x10d35eaa0>
這段代碼中mygenerator
就是一個迭代器, 跟上文的mylist2
生成方式有點點區別, []
改爲了()
, 從使用上來講, generators
和iterables
都是相似for in
的這種方式string
可是 : generators
不是保存在內存中的, 而是惰性加載的, 也就是你用到它的時候, 它才臨時去計算, 只能使用一次for in
, 好比上面的mygenerator
, 計算0*0
並返回以後就不在保留了, 繼續計算1*1
it
適用場景: 當須要迭代訪問一組量很是大的數據集的時候, generator
是很是有用的, 由於它計算完了前面的數據而後就計算後面, 並不在內存裏保留全部的數據, 這樣就不至於內存爆掉io
理解了generator
以後, 再來看yield
就很是好理解了, 能夠把yield
當成return
看待object
>>> def createGenerator(): ... mylist = range(3) ... for i in mylist: ... yield i*i ... >>> mygenerator = createGenerator() # 建立一個生成器, 這裏createGenerator內的代碼並無運行 >>> print(mygenerator) # 生成器就是一個object <generator object createGenerator at 0xb7555c34> >>> >>> for i in mygenerator: # 這裏createGenerator內的代碼纔開始運行 ... print(i) 0 1 4
上面的代碼中當調用createGenerator()
的時候, 其實方法內的代碼並無運行, 而在for in
循環訪問的時候, 纔開始從頭計算, 當運行到yield
的時候返回第一個值, 而後就停
下來, 當再次請求數據的時候繼續運算直到再次碰到yield
... 直到沒有值能夠返回file