原文: https://stackoverflow.com/que...個人微信公衆號:python每日一練python
要理解什麼是 yield
,必須理解什麼是生成器(generator)。在理解生成器以前,讓咱們先了解迭代。微信
迭代函數
當你創建了一個列表,你能夠逐個地訪問這個列表的元素,而這個訪問的過程叫作迭代(iteration)code
>>> mylist = [1, 2, 3] >>> for i in mylist: ... print(i) 1 2 3
代碼中的mylist
就是一個可迭代對象(iterable),當你使用列表生成式時,你就建立了一個list
,同時也建立了一個可迭代對象:對象
>>> mylist = [x*x for x in range(3)] >>> for i in mylist: ... print(i) 0 1 4
凡是能使用for...in...
語句的對象,都叫作可迭代對象,例如:list
、string
、文件等等內存
這些可迭代對象很是方便,由於你能夠根據本身的須要來訪問它們。可是同時也須要將全部的值存入內存當中,不管你是否是須要全部的值,可能對於一個列表[x for x in range(100000)]
,你僅僅想拿到裏面的素數,但當這個列表生成式被執行的時候,已經將全部100000個數字存入了內存中。get
生成器generator
生成器是一種只能迭代一次的迭代器,生成器不會一次將全部的元素存入內存中,而是一邊迭代一邊運算:string
>>> mygenerator = (x*x for x in range(3)) >>> for i in mygenerator: ... print(i) 0 1 4
這份代碼看起來和上面的代碼沒有什麼區別。可是你不能再次執行for i in mygenerator
,由於生成器只能使用一次:it
>>> mygenerator = (x*x for x in range(3)) >>> for i in mygenerator: ... print(i) ... 0 1 4 >>> for i in mygenerator: ... print(i) ... >>>
Yield
yield
的使用和return
的使用沒什麼區別,只是yield
會返回一個生成器
>>> def createGenerator(): ... mylist = range(3) ... for i in mylist: ... yield i*i ... >>> mygenerator = createGenerator() # 建立一個生成器 >>> print(mygenerator) # mygenerator是一個對象! <generator object createGenerator at 0xb7555c34> >>> for i in mygenerator: ... print(i) 0 1 4
當你的函數須要返回一個很大的元素集合,而且每一個元素只須要用到一次的時候,使用yield
會很是方便
要想理解yield
,你必須理解當你調用一個包含yield
的函數的時候,函數體代碼並不會執行,這個函數僅僅是返回一個生成器而已
>>> def createGenerator(): ... print('head') ... for i in range(5): ... yield i*i ... print('tail') ... >>> createGenerator() <generator object createGenerator at 0x0000023454FB5990>
當你第一次向後迭代(用next
或for...in...
語句時)這個生成器時,函數體纔會從最開始執行到yield
處而後返回yield
的值,隨後再次向後迭代,會執行剩餘的代碼而後再次遇到yield
中止並返回值。直到運行到函數結尾處中止,此時若是是用next()
則會拋出StopIteration
異常,若是是用for...in...
則會結束循環而且不會有異常
>>> def createGenerator(): ... print('head') ... for i in range(5): ... yield i*i ... print('tail') ... >>> g = createGenerator() >>> next(g) head 0 >>> next(g) 1 >>> next(g) 4 >>> next(g) 9 >>> next(g) 16 >>> next(g) tail Traceback (most recent call last): File "<stdin>", line 1, in <module> StopIteration