姓名:曾國(guó)強(qiáng)
學(xué)號(hào):19021210984
轉(zhuǎn)載自https://zhuanlan.zhihu.com/p/76831058
【嵌牛導(dǎo)讀】python中的迭代器是遵循迭代協(xié)議的對(duì)象,生成器可理解為一種數(shù)據(jù)類型,其自動(dòng)實(shí)現(xiàn)迭代器協(xié)議。
【嵌牛正文】
1、迭代器協(xié)議
對(duì)象必須提供一個(gè)next方法,執(zhí)行該方法后,要么返回迭代的下一項(xiàng),要么引起StopIteraction異常,終止迭代
2、迭代器和迭代過程
很多容器諸如列表、字符串可以用for循環(huán)遍歷對(duì)象。for 語(yǔ)句會(huì)調(diào)用容器對(duì)象中的 iter()函數(shù), 該函數(shù)返回一個(gè)定義了 __next__() 方法的迭代器對(duì)象,該方法將逐一訪問容器中的元素。
所以說:python中,任意對(duì)象,只要定義了__next__方法,它就是一個(gè)迭代器。因此,python中的容器如列表、元組、字典、集合、字符串都可以被稱作迭代器。
講完迭代器后,迭代就比較好理解了,迭代就是從迭代器中取元素的過程。
比如我們用for循環(huán)從列表[1,2,3]中取元素,這種遍歷過程就被稱作迭代。
# 列表是迭代器
for element in [1, 2, 3]:
?????print(element)
# 元組是迭代器
for element in (1, 2, 3):
?????print(element)
# 字典是迭代器
for key in {'one':1, 'two':2}:?
????print(key)
# 字符串是迭代器
for char in "123":?
????print(char)
# 打開的text同樣是迭代器
for line in open("myfile.txt"):?
????print(line, end='')
如果你不想用for循環(huán)迭代呢?這時(shí)你可以:
先調(diào)用容器(以字符串為例)的iter()函數(shù)
再使用 next() 內(nèi)置函數(shù)來調(diào)用 __next__() 方法
當(dāng)元素用盡時(shí),__next__() 將引發(fā) StopIteration 異常

3、生成器?
生成器也是一種迭代器,但是你只能對(duì)其迭代一次。這是因?yàn)樗鼈儾]有把所有的值存在內(nèi)存中,而是在運(yùn)行時(shí)生成值。
你通過遍歷來使用它們,要么用一個(gè)for循環(huán),要么將它們傳遞給任意可以進(jìn)行迭代的函數(shù)和結(jié)構(gòu)。大多數(shù)時(shí)候生成器是以函數(shù)來實(shí)現(xiàn)的。然而,它們并不返回一個(gè)值,而是yield(暫且譯作“生出”)一個(gè)值。
每次對(duì)生成器調(diào)用 next() 時(shí),它會(huì)從上次離開位置恢復(fù)執(zhí)行(它會(huì)記住上次執(zhí)行語(yǔ)句時(shí)的所有數(shù)據(jù)值)。顯示如何非常容易地創(chuàng)建生成器的示例如下:
def reverse(data):
? ? for index in range(len(data)-1, -1, -1):
? ? ? ? yield data[index]
>>> for char in reverse('golf'):
...? ? print(char)
...
f
l
o
g
可以用生成器來完成的操作同樣可以用前一節(jié)所描述的基于類的迭代器來完成。但生成器的寫法更為緊湊,因?yàn)樗鼤?huì)自動(dòng)建 __iter__() 和 __next__()方法。
4、生成器表達(dá)式
生成器不一定要用復(fù)雜的函數(shù)表示,python提供了簡(jiǎn)潔的生成器表達(dá)式。
從形式上來看,生成器表達(dá)式和列表推導(dǎo)式很像,僅僅是將列表推導(dǎo)式中的[]替換為(),但是兩者差別挺大,生成器表達(dá)式可以說組合了迭代功能和列表解析功能。
生成器表達(dá)式可以認(rèn)為是一種特殊的生成器函數(shù),類似于lambda表達(dá)式和普通函數(shù)。但是和生成器一樣,生成器表達(dá)式也是返回生成器generator對(duì)象,一次只返回一個(gè)值。
>>> sum(i*i for i in range(10)) # sum of squares
285
>>> xvec = [10, 20, 30]
>>> yvec = [7, 5, 3]
>>> sum(x*y for x,y in zip(xvec, yvec))? ? ? ? # dot product
260
>>> from math import pi, sin
>>> sine_table = {x: sin(x*pi/180) for x in range(0, 91)}
>>> unique_words = set(word? for line in page? for word in line.split())
>>> valedictorian = max((student.gpa, student.name) for student in graduates)
>>> data = 'golf'
>>> list(data[i] for i in range(len(data)-1, -1, -1))
['f', 'l', 'o', 'g']