Python3學習之路~4.2 迭代器
可以直接作用於for
迴圈的資料型別有以下幾種:
一類是集合資料型別,如list
、tuple
、dict
、set
、str
等;
一類是generator
,包括生成器和帶yield
的generator function。
這些可以直接作用於for
迴圈的物件統稱為可迭代物件:Iterable
。
可以使用isinstance()
判斷一個物件是否是Iterable
物件:
from collections import Iterable def fib(max): n,a,b=0,0,1 while n<max: #print(b)View Codeyield b a,b = b,a+b n=n+1 return 'done' print(isinstance([],Iterable)) # True print(isinstance((),Iterable)) # True print(isinstance({},Iterable)) # True print(isinstance(set([]),Iterable)) # True print(isinstance('abc',Iterable)) # True print(isinstance((x forx in range(10)),Iterable)) # True print(isinstance(fib(10),Iterable)) # True print(isinstance(100,Iterable)) # False
而生成器不但可以作用於for
迴圈,還可以被next()
函式不斷呼叫並返回下一個值,直到最後丟擲StopIteration
錯誤表示無法繼續返回下一個值了。
*可以被next()
函式呼叫並不斷返回下一個值的物件稱為迭代器:Iterator
。
可以使用isinstance()
判斷一個物件是否是Iterator
物件:
fromView Codecollections import Iterator def fib(max): n,a,b=0,0,1 while n<max: #print(b) yield b a,b = b,a+b n=n+1 return 'done' print(isinstance([],Iterator)) # False print(isinstance((),Iterator)) # False print(isinstance({},Iterator)) # False print(isinstance(set([]),Iterator)) # False print(isinstance('abc',Iterator)) # False print(isinstance((x for x in range(10)),Iterator)) # True print(isinstance(fib(10),Iterator)) # True print(isinstance(100,Iterator)) # False
生成器都是Iterator
物件,但list
、tuple
、dict
、set
、str等
雖然是Iterable
,卻不是Iterator
。
把list
、tuple
、dict
、set
、str
等Iterable
變成Iterator
可以使用iter()
函式:
from collections import Iterator print(isinstance(iter([]),Iterator)) # True print(isinstance(iter(()),Iterator)) # True print(isinstance(iter({}),Iterator)) # True print(isinstance(iter(set([])),Iterator)) # True print(isinstance(iter('abc'),Iterator)) # TrueView Code
你可能會問,為什麼list
、tuple
、dict
、set
、str
等資料型別不是Iterator
?
這是因為Python的Iterator
物件表示的是一個數據流,Iterator物件可以被next()
函式呼叫並不斷返回下一個資料,直到沒有資料時丟擲StopIteration
錯誤。可以把這個資料流看做是一個有序序列,但我們卻不能提前知道序列的長度,只能不斷通過next()
函式實現按需計算下一個資料,所以Iterator
的計算是惰性的,只有在需要返回下一個資料時它才會計算。
Iterator
甚至可以表示一個無限大的資料流,例如全體自然數。而使用list是永遠不可能儲存全體自然數的。
小結
凡是可作用於for
迴圈的物件都是Iterable
型別;
凡是可作用於next()
函式的物件都是Iterator
型別,它們表示一個惰性計算的序列;
集合資料型別如list
、tuple
、dict
、set
、str
等是Iterable
但不是Iterator
,不過可以通過iter()
函式獲得一個Iterator
物件。
Python的for
迴圈本質上就是通過不斷呼叫next()
函式實現的,例如:
for x in [1, 2, 3, 4, 5]: pass
實際上完全等價於:
# 首先獲得Iterator物件: it = iter([1, 2, 3, 4, 5]) # 迴圈: while True: try: # 獲得下一個值: x = next(it) except StopIteration: # 遇到StopIteration就退出迴圈 break
另外,在Python2.7中,range()生成一個列表,xrange()生成一個生成器。
在Python3.5中,range()直接生成一個生成器,xrange()沒有了。
#python 2.7 >>> range(10) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> type(range(10)) <type 'list'> >>> xrange(10) xrange(10) >>> type(xrange(10)) <type 'xrange'> #python 3.5 >>> range(10) range(0, 10) >>> type(range(10)) <class 'range'> >>> xrange(10) Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: name 'xrange' is not definedView Code
檔案也是一種迭代器Iterator
from collections import Iterable from collections import Iterator f=open('yesterday.txt',encoding='UTF-8') print(isinstance(f,Iterable)) #True print(isinstance(f,Iterator)) #TrueView Code