可迭代對(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__()))

?????我們對(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__())

?????在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__())

?????如果用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))

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è)迭代器。