Python迭代器與可迭代物件

2021-09-07 08:07:04 字數 4059 閱讀 6695

當掃瞄記憶體中放不下的資料集時,我們需要找到一種惰性獲取資料項的方式,每次「取出」1個。

這就是迭代器相對於普通可迭代物件的優勢:節省記憶體

l =[,

'orange'

,'pear'

]#列表就是乙個可迭代物件

在python中,很多內建的資料型別都是可迭代物件,如列表,字串,元組,字典,集合等

如果要自己構建乙個可迭代的資料型別,只需要實現乙個__getitem__()方法。

接下來實現乙個sentence類,傳入乙個以空格分隔的英文句子,迭代句子中的單詞。

class

sentence

:def

__init__

(self, text)

: self.words = text.split(

)def

__getitem__

(self, index)

:return self.words[index]

現在測試一下這個sentence類

>>

> sen = sentence(

'hello my world my name is alfred'

)>>

> sen

<__main__.sentence object at 0x02cf5f30

>

>>

> sen.words

['hello'

,'my'

,'world'

,'my'

,'name'

,'is'

,'alfred'

]>>

> sen[3]

'my'

>>

>

for i in sen:

print

(i)hello

myworld

myname

isalfred

剛才我利用__getitem__()構建了乙個可迭代物件sen,

那麼如果我要構建乙個迭代器,應該使用的魔法方法是__next__()和__iter__()

接下來利用__next__()和__iter__()構建乙個sentence2類。

class

sentence2

:def

__init__

(self, text)

: self.words = text.split(

) self.index =

0def

__next__

(self)

:try

: word = self.words[self.index]

except indexerror:

raise stopiteration(

) self.index +=

1return word

def__iter__

(self)

:return self

同樣地,現在來測試一下這個sentence2類

>>

> sen2 = sentence2(

'hello my world my name is alfred'

)>>

> sen2.words

['hello'

,'my'

,'world'

,'my'

,'name'

,'is'

,'alfred'

]>>

> sen2[5]

traceback (most recent call last)

: file ""

, line 1,in

sen2[5]

typeerror:

'sentence2'

object does not support indexing

>>

>

for i in sen2:

print

(i)hello

myworld

myname

isalfred

>>

>

sen2的索引操作引發了typeerror異常,然而從for迴圈中可以看出,sen2依然是可迭代的。其實這裡還有乙個很神奇的現象,如果對sen2進行第二次for迴圈,會發現什麼都得不到,sen2裡面是空的。

>>

>

for i in sen2:

print

(i)>>

>

實際上,當我們迭代乙個物件x的時候,直譯器會自動呼叫內建的iter(x)函式。它的作用有3個:

(1)檢查物件是否實現了__iter__()方法,如果實現了就呼叫它,返回乙個迭代器。

(2)如果沒有實現__iter__(),就檢查是否實現了__getitem__()方法,python會自動建立乙個迭代器,並從索引0開始獲取元素。

(3)如果2個方法都沒有實現,那麼就只能丟擲typeerror異常了「x object is not iterable」

為什麼在上述的sen2例項中,進行第二次迭代的時候,sen2會沒有元素可以迭代呢?

這是由於__iter__()方法使其自身成為了迭代器,當迭代的時候,next()方法會不斷地返回序列中的下乙個元素,最終導致耗盡了其自身的元素,然後丟擲stopiteration異常。

為了讓迭代器可以一直迭代,iter()方法應該是返回乙個迭代器,而不是讓其自身稱為乙個迭代器

所以,迭代器更準確的實現方式應該是只實現乙個__iter__()方法,而__next__()方法應該封裝在另乙個類中,該類表示了迭代器的內部狀態:

譬如如下sentence3類:

class

sentence3

:def

__init__

(self, text)

: self.words = text.split(

)def

__iter__

(self)

:return sentenceiter(self.words)

class

sentenceiter

:def

__init__

(self, words)

: self.words = words

self.index =

0def

__next__

(self)

:try

: word = self.words[self.index]

except indexerror:

raise stopiteration(

) self.index +=

1return word

def__iter__

(self)

:return self

現在sen3可以一直迭代了

>>

> sen3 = sentence3(

'hello my world my name is alfred'

)>>

> sen3.words

['hello'

,'my'

,'world'

,'my'

,'name'

,'is'

,'alfred'

]>>

>

for i in sen3:

print

(i)

hello

myworld

myname

isalfred

>>

>

for i in sen3:

print

(i)

hello

myworld

myname

isalfred

>>

>

總的來說:

python迭代 可迭代物件與迭代器物件

問題舉例 某軟體要求,從網路抓取各個城市的氣溫資訊,並依次顯示 北京 15 22 上海 18 23 如果一次抓取所有城市氣溫資訊再顯示,顯示第乙個城市的氣溫時會由很長的延時,並且浪費儲存空間,我們期望以 用時訪問 的策略,並且把所有城市的氣溫資訊封裝 到乙個物件裡,可用for語句進行迭代。來個栗子 ...

python 迭代器與可迭代物件

主要有兩個方法next 與iter next不斷返回下乙個元素,知道元素全部返回後出現異常,可以節省記憶體空間。iter是迭代,可以把乙個列表直接轉換成迭代器,然後使用next 方法。data list 1,2,3,4,5 data list iter data list print next da...

Python 迭代器與可迭代物件

迭代器可以讓我們訪問集合的時候變得非常方便。之前我們通過for.in.的方式訪問乙個集合的時候,就是使用迭代器完成的。如果沒有迭代器,那麼我們只能通過while迴圈,每次迴圈的時候通過下標訪問了。可以直接使用for迴圈遍歷的物件,成為可迭代的物件,常見的可迭代的物件有 list tuple dict...