一、可迭代對象和迭代器
1. 可迭代對象的概念
-
可迭代對象就是有__iter__屬性的對象
-
Iterable對象的本質是該對象內部實現了一個__iter__方法,也可使用dir函數通過判斷該對象是否有__iter__方法來判別是否爲Iterable對象。
-
繼承迭代器對象,可以用for循環(說明實現了iter方法),只要可以用作for循環的都是可迭代對象
-
使用for循環實際上幹了兩件事,首先調用__iter__返回一個對象,該對象必須有__next__方法,然後再循環調用該對象的__next__方法不斷獲取下一個值。
常見的對象比如string、list、tuple、dict都是Iterable對象,他們都可以for循環遍歷每一個元素
2. 迭代器的概念
- 同時實現了__iter__、__next__方法的對象爲迭代器,若一個對象定義了__next__方法,則除了for循環外,還可以將該對象作爲next方法的輸入參數以獲取下一個迭代值。
- 迭代器(Iterator)它是一種接口,爲各種不同的數據結構提供統一的訪問機制。 任何數據結構只要部署Iterator接口,就可以完成遍歷操作(即依次處理該數據結構的所有成員)。
- 對於迭代器來說,iter 返回的是它自身 self,next 則是返回迭代器中的下一個值,如果沒有值了則拋出一個 StopIteration 的異常。
- 一個迭代器一定是可迭代對象,因爲它一定有 iter 方法。反過來則不成立。(事實上,Iterator 就是 Iterable 的子類)
- 只要可以用next()函數的都是迭代器對象
- 迭代器的作用:
- (1)是爲各種數據結構,提供一個統一的、簡便的訪問接口;
- (2)是使得數據接口的成員能夠按照某種次序排列;
- (3)是ES6創造了一種新的遍歷命令for…of循環,Iterator接口主要提供for…of消費
3. 判斷該對象是否可迭代的兩種方式
- (1)iter(x)
- 這是最準確的判斷方式,傳入要判斷的對象,只要對象實現了__getitem__ 、 __iter__中的其中一個,該對象都是可迭代的,否則拋出TypeError: ‘C’ object is not iterable 異常;這兒有個區別,如果 僅僅實現了 getitem ,調用 iter(x) 返回的是迭代器對象,如果 實現的是 iter ,那麼調用 iter(x) 返回的是生成器對象;
- (2)isinstance(x, abc.Iterable)
- 該方式會自動忽略 getitem 函數,僅當對象實現了 iter 函數才返回 True,其他一律返回 False
4. 可迭代對象轉換成迭代器
用iter()方法即可
from collections import Iterable,Iterator
a = [1,2,3]
a = iter(a)
print(isinstance(a,Iterator))
print(isinstance(a,Iterable))
print(next(a))
print('----')
for x in a:
print(x)
返回結果:
True
True
1
----
2
3
可以看到現在a是可迭代對象又是一個迭代器,說明列表a中有iter方法,該方法返回的是迭代器,這個時候使用next就可以獲取a的下一個值,但是要記住迭代器中的數值只能被獲取一次。
總結:
- 有__iter__方法的對象都是可迭代對象,__iter__方法返回的對象必須含有__next__方法。
- 同時有__iter__和__next__方法的對象爲迭代器。
- 僅有__next__方法的對象不能用for循環遍歷,而可以用next方法遍歷。
- 因此我們在自定義可迭代對象需要實現 iter 函數;嚴格來講,我們還需要實現 getitem 函數,這個函數的主要作用是當前對象可通過下標取值。
- 使用迭代器的好處在於:它是一種延遲操作,即當需要用到的時候纔去產生結果。比如對於一個序列來說,如果我們要遍歷它,並不需要再一開始就把所有元素都生成好,而是隻需要知道每個元素的下一個元素是什麼就可以了。這樣可以節省很多空間,尤其對於數量很大的集合來說。