可以直接作用于for循環(huán)的數(shù)據(jù)類型有以下幾種:
- 一類是集合數(shù)據(jù)類型傍念,如list、tuple葛闷、dict憋槐、set、str等
- 一類是generator淑趾,包括生成器和帶yield的generator function阳仔。
這些可以直接作用于for循環(huán)的對象統(tǒng)稱為可迭代對象:Iterable。
可以使用isinstance()判斷一個(gè)對象是否是Iterable對象:
>>> from collections import Iterable
>>> isinstance([], Iterable)
True
而生成器不但可以作用于for循環(huán)扣泊,還可以被next()函數(shù)不斷調(diào)用并返回下一個(gè)值近范,直到最后拋出StopIteration錯(cuò)誤表示無法繼續(xù)返回下一個(gè)值了
可以被next()函數(shù)調(diào)用并不斷返回下一個(gè)值的對象稱為迭代器:Iterator
可以使用isinstance()判斷一個(gè)對象是否是Iterator對象:
>>>from collections import Iterator
>>>isinstance((x for x in range(10)), Iterator)
True
>>>isinstance([], Iterator)
True
注意:
[x for x in range(10)] : 列表生成式
(x for x in range(10)) : 生成器
生成器都是Iterator對象,但list延蟹、dict评矩、str雖然是Iterable,卻不是Iterator阱飘。
把list斥杜、dict虱颗、str等Iterable變成Iterator可以使用iter()函數(shù)
>>> isinstance(iter([]), Iterator)
True
你可能會(huì)問,為什么list蔗喂、dict忘渔、str等數(shù)據(jù)類型不是Iterator?
這是因?yàn)镻ython的Iterator對象表示的是一個(gè)數(shù)據(jù)流缰儿,Iterator對象可以被next()函數(shù)調(diào)用并不斷返回下一個(gè)數(shù)據(jù)畦粮,直到?jīng)]有數(shù)據(jù)時(shí)拋出StopIteration錯(cuò)誤」哉螅可以把這個(gè)數(shù)據(jù)流看做是一個(gè)有序序列宣赔,但我們卻不能提前知道序列的長度,只能不斷通過next()函數(shù)實(shí)現(xiàn)按需計(jì)算下一個(gè)數(shù)據(jù)瞪浸,所以Iterator的計(jì)算是惰性的儒将,只有在需要返回下一個(gè)數(shù)據(jù)時(shí)它才會(huì)計(jì)算
Iterator甚至可以表示一個(gè)無限大的數(shù)據(jù)流,例如全體自然數(shù)默终。而使用list是永遠(yuǎn)不可能存儲(chǔ)全體自然數(shù)的
小結(jié):
- 凡是可作用于for循環(huán)的對象都是Iterable類型椅棺;
- 凡是可作用于next()函數(shù)的對象都是Iterator類型犁罩,它們表示一個(gè)惰性計(jì)算的序列齐蔽;
- 集合數(shù)據(jù)類型如list、dict床估、str等是Iterable但不是Iterator含滴,不過可以通過iter()函數(shù)獲得一個(gè)Iterator對象。
- Python的for循環(huán)本質(zhì)上就是通過不斷調(diào)用next()函數(shù)實(shí)現(xiàn)的丐巫。
for x in [1, 2, 3, 4, 5]:
pass
實(shí)際上完全等價(jià)于:
# 首先獲得Iterator對象:
it = iter([1, 2, 3, 4, 5])
# 循環(huán):
while True:
try:
# 獲得下一個(gè)值:
x = next(it)
except StopIteration:
# 遇到StopIteration就退出循環(huán)
break