可迭代對象和迭代器是常常碰到但又很容易混淆的兩個概念,因此今天小編跟你們深刻剖析一下可迭代對象和迭代器的區別。認真看完本文,你將收穫:python
事不宜遲,咱們立刻開始吧!函數
要理解可迭代對象,那首先要搞清楚迭代的概念。關於迭代,維基百科是這樣子定義的:spa
迭代是重複反饋過程的活動,其目的一般是爲了接近併到達所需的目標或結果。每一次對過程的重複被稱爲一次「迭代」,而每一次迭代獲得的結果會被用來做爲下一次迭代的初始值。
從這個定義中,咱們大概能夠知道迭代是對某一個過程的重複。其實在程序中,迭代也是相似的,它是一種遍歷集合元素的方式,請看下面的示例1。code
# 示例1 for i in [1,2,3]: print(i)
輸出結果:component
1 2 3
在示例1中,解釋器重複地從列表中取出元素並打印,直到遍歷結束爲止,這就是一個迭代的過程。可見,可迭代對象能夠在for循環中遍歷元素。對象
那什麼樣的對象纔是一個可迭代對象?事實上,只要實現 iter 方法或者實現 __ getitem __方法並且其參數從0開始索引,那麼該對象就是可迭代對象,請看示例2。blog
#示例2 class Vector(object): def __init__(self,components): self.components = list(components) def __iter__(self): return iter(self.components) V1 = Vector([1,2,3]) for i in V1: print(i)
輸出結果:索引
1 2 3
從示例2中可見,Vector類實現了 __ iter __方法,解釋器能夠從Vector類對象中重複地取出元素並打印。若是要檢查某一個對象是否爲可迭代對象,其實可使用isinstance( )函數,該函數用於判斷對象是否爲某一類型,可是用這個函數判斷不必定準確(緣由後面會說到)。ip
from collections.abc import Iterable print(isinstance(V1,Iterable))#True
若是咱們只是實現了__ getitem __ ()方法,狀況又會怎麼樣呢?請看示例3。rem
# 示例3 from collections.abc import Iterable class Vector(object): def __init__(self,components): self.components = list(components) def __getitem__(self,index): return self.components[index] V1 = Vector([1,2,3]) for i in V1: print(i) print(isinstance(V1,Iterable))
輸出結果:
1 2 3 Flase
從示例3中可看到,Vector實現了__ getitem__方法,解釋器能夠對V1進行迭代並打印元素,可是!使用isinstance()判斷時,返回的結果竟然是False。明明可使用for循環來迭代元素,爲何是判斷是Flase呢?事實上,若是可迭代對象只是實現了__ getitem __ 的話,abc.Iterable是不考慮該方法的,這便致使了isinstance()判斷不許確。更準確的方法應該是調用iter()函數,若是該對象不可迭代,就會拋出TypeError的錯誤。咱們嘗試使用iter()來判斷一下。
# 示例4 print(iter(V1)) #<iterator object at 0x000001B262E35518> #去掉__getitem__方法後 print(iter(V1)) #TypeError: 'Vector' object is not iterable
從示例4中能夠看到,對於可迭代對象,iter()會返回< iterator object at xxxx >。當去掉__ getitem __ ()方法後再檢查時,便拋出TypeError錯誤。iter()函數用於生成一個迭代器,也就是說能夠返回一個迭代器的就是一個可迭代對象。
該對象之因此能迭代,是由於實現了__iter__()方法。當使用for循環時候,解釋器會檢查對象是否有__ iter__ ()方法,有的話就是調用它來獲取一個迭代器。因此沒有__ iter__ ()方法但實現了__ getitem __ (),解釋器會建立一個迭代器,嘗試從0開始按順序遍歷元素。若是嘗試失敗,Python便會拋出TypeError錯誤。
那麼Python內置類型中究竟有哪些可迭代對象呢?咱們一塊兒盤點一下吧。
其實盤點出來的都是序列,因此說任何序列都是可迭代的對象, 其緣由在於他們至少都會實現__ getittem __ 方法(序列均可以經過索引獲取元素)。
在介紹可迭代對象時候說到,當使用for循環時候,解釋器會檢查對象是否有__ iter __ ()方法,有的話就是調用它來獲取一個迭代器。那麼究竟什麼是迭代器呢?
其實迭代器是實現了__iter__方法和__next__方法的對象。__ iter__ 方法用於返回迭代器自己,而__ next __ 用於返回下一個元素。咱們自定義一個迭代器,以斐波那契數列爲例說明一下其內部的執行狀況,看示例5。
# 示例5 import itertools class Fib: def __init__(self): self.pre = 0 self.cur = 1 def __iter__(self): return self def __next__(self): p = self.cur self.cur += self.pre self.pre = p return p f = Fib() a = list(itertools.islice(f,0,10)) print(a) #[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
從示例5中__ iter__ ()返回了迭代器對象自己,以便在使用可迭代對象的地方(如for循環中)使用迭代器,而__ next __ ()則經過計算返回下一個元素。咱們再一塊兒看看下面的示例6。
#示例6 >>>s = 'ABCD' >>>it = iter(s) >>>while True:print(next(it)) A B C D --------------------------------------------------------------------------- StopIteration Traceback (most recent call last) <ipython-input-4-d09d5cde4495> in <module>() ----> 1 while True:print(next(it)) StopIteration: >>> list(it) [] >>>list(iter(s)) ['A','B','C','D']
在示例6中先定義一個字符串的可迭代對象,經過iter()函數返回一個迭代器(會自動調用對象的__ iter__ 方法),而後在循環中經過next()取值並打印(會自動調用對象 __ next __()方法),經過next()方法一個個地遍歷可迭代對象中的元素,當遍歷結束,便會拋出StopIteratioin異常,這時迭代器也沒用了,若是要再次迭代,就要使用iter()函數從新構建迭代器。
經過示例5和示例6,咱們可知道迭代器是一個能夠記住遍歷位置的對象,其內部有一個狀態用於記錄迭代所在的位置,以便下次迭代時候能取出正確的元素。迭代器就像一個懶人同樣,當你須要數據時候纔會返回給你,不然就在等待下一次的調用。
若是要檢查某個對象是否爲迭代器,最好的方式是使用isinstance( )函數,見示例7。
# 示例7 from collections.abc import Iterator f = Fib() print(isinstance(f,Iterator)) #True
好了,說了那麼多,究竟迭代器哪些用處呢?其實在Python語言內部,迭代器用於支持:
以上就是小編今天跟你們分享的內容了,若是有什麼疑問記得聯繫小編哦~
公衆號:CVpython,專一於分享Python和計算機視覺,咱們堅持原創,不按期更新,但願文章對你有幫助,快點掃碼關注吧。