迭代器

可迭代對(duì)象

?????可以用for循環(huán)的都是可迭代對(duì)象,那么為什么有的對(duì)象可以用for循環(huán),而有的確不行呢?

list
tuple
dict
set
range()
enumerate()
....

?????這些對(duì)象都可以用for循環(huán)取得想要的值。

ls = dir(list)
tu = dir(tuple)
di = dir(dict)
se = dir(set)
ra = dir(range(10))
en = dir(enumerate([]))
#使用dir獲得參數(shù)的屬性,方法列表
s = set(ls) & set(tu) & set(di) & set(se) & set(ra) & set(en)
#取交集
print(s)

?????在這些交集中有一個(gè)屬性為__iter__。也正是因?yàn)檫@個(gè)屬性,它們才可以被迭代,也就是用for循環(huán)。
?????綜上,當(dāng)一個(gè)對(duì)象擁有__iter__方法時(shí),它就是一個(gè)可迭代對(duì)象,也就可以用for循環(huán)。

迭代器

print(type([].__iter__()))
迭代器.png

?????我們對(duì)列表使用一下__iter__()方法,查看它的類型發(fā)現(xiàn)它變成了iterator,也就是迭代器

print(dir([].__iter__()))
ls = [1,2,3]
iterator = ls.__iter__()
print(iterator.__next__())
print(iterator.__next__())
print(iterator.__next__())
迭代器.png

?????在iterator的眾多方法中有一個(gè)叫做__next__()的方法,使用它可以依次得到iterator中的值。
?????同樣它也有一個(gè)__iter__()方法,說明可以對(duì)iterator進(jìn)行for循環(huán)

ls = [1,2,3]
iterator = ls.__iter__()
for i in iterator:
    print(i)

?????當(dāng)然我們也可以使用while

ls = [1,2,3]
iterator = ls.__iter__()
while True:
    print(iterator.__next__())
迭代器.png

?????如果用while True將會(huì)一直取下一個(gè)元素,但如果沒有下一個(gè)元素了怎么辦,這時(shí)就會(huì)拋出一個(gè)StopIterator的異常,表示已經(jīng)取到最后一個(gè)了,不能再往下繼續(xù)了。

?????現(xiàn)在來說說for的工作原理,如果給它的不是一個(gè)可迭代對(duì)象,它就直接報(bào)錯(cuò),如果給它一個(gè)可迭代對(duì)象像list...它會(huì)先調(diào)用內(nèi)置的__iter__()方法得到該對(duì)象的迭代器對(duì)象,然后調(diào)用迭代器對(duì)象的__next__()方法,一直依次向下取得迭代器對(duì)象中的每一個(gè)元素,直到迭代器沒有下一個(gè)元素了。如果給它的直接是一個(gè)迭代器對(duì)象,那么就直接調(diào)用__next__()方法

Tips:

  • 如果一個(gè)對(duì)象有__iter__()方法,那么它就是一個(gè)可迭代對(duì)象
  • 如果一個(gè)對(duì)象既有__iter__()方法,又有__next__()方法,那么它就是一個(gè)迭代器對(duì)象
  • 由以上兩點(diǎn),迭代器一定是可迭代對(duì)象,但可迭代對(duì)象不一定是迭代器
  • 一個(gè)可迭代對(duì)象調(diào)用它的__iter__()方法,就可以返回一個(gè)迭代器對(duì)象
  • 調(diào)用迭代器的__next__()方法,可以一個(gè)一個(gè)地獲取值。

isinstance

?????如果我們要判斷一個(gè)對(duì)象是不是一個(gè)可迭代對(duì)象或者是一個(gè)迭代器對(duì)象的時(shí)候,我們?nèi)ゲ榭磀ir,一個(gè)一個(gè)找它們是不是有__iter__()或是__next__(),實(shí)在太low,這時(shí)候我們使用isinstance()函數(shù)即可判斷。

from collections import Iterable,Iterator
print(isinstance([],Iterable))
print(isinstance([],Iterator))
print(isinstance({1,2,3},Iterable))
迭代器.png

xrange和range

?????現(xiàn)在討論這個(gè)問題可能已經(jīng)沒有多大意義了,因?yàn)樵赑ython3.x中xrange和range被統(tǒng)一為range

  • 在Python2.x中使用range()是生成一個(gè)序列
  • 在Python2.x中使用xrange()是生成一個(gè)迭代器,要一個(gè)值取一個(gè),不需要一次性開辟一塊很大的內(nèi)存空間。因此在性能上xrange會(huì)比range更優(yōu)。
    在Python3.x中xrange被range取代,也就是說只有range存在,并且生成的是一個(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)容