[譯]yield關鍵字都作了什麼?

原文: 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...語句的對象,都叫作可迭代對象,例如:liststring、文件等等內存

這些可迭代對象很是方便,由於你能夠根據本身的須要來訪問它們。可是同時也須要將全部的值存入內存當中,不管你是否是須要全部的值,可能對於一個列表[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>

當你第一次向後迭代(用nextfor...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
相關文章
相關標籤/搜索