python生成器和迭代器

姓名:曾國(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']

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容