Python:叠代器
在使用Python的過程中,很容易混淆如下幾個關聯的概念:
- 容器(container)
- 可叠代對象(Iterable)
- 叠代器(Iterator)
- 生成器(generator)
- 生成器表達式
- {list, set, dict} 解析式
1.容器(container)
容器是用來儲存元素的一種數據結構,它支持隸屬測試,容器將所有數據保存在內存中,在Python中典型的容器有:
- list, deque, ...
- set,frozesets,...
- dict, defaultdict, OrderedDict, Counter, ...
- tuple, namedtuple, ...
- str
通過判斷一個對象是否包含某個元素來確定它是否為一個容器
>>> assert 1 in [1,2,3] # lists >>> assert 4 not in [1,2,3] >>> assert 1 in {1,2,3} # sets >>> assert 4 not in {1,2,3} >>> assert 1 in (12,3) # tuples >>> assert 4 not in (1,2,3)
字典容器通過檢查是否包含某個鍵來進行判斷
>>> d = {1:"foo", 2:"bar", 3:"qux"} >>> assert 1 in d >>> assert 4 in d Traceback (most recent call last): File "<stdin>", line 1, in <module> AssertionError >>> assert "foo" in d Traceback (most recent call last): File "<stdin>", line 1, in<module> AssertionError
字符串通過檢查是否包含某個子 串來判斷
>>> s="foo" >>> assert "f" in s >>> assert "b" in s Traceback (most recent call last): File "<stdin>", line 1, in <module> AssertionError
2.可叠代對象
如果給定一個list或tuple,我們可以通過for
循環來遍歷這個list或tuple,這種遍歷我們稱為叠代(Iteration)。
很多容器都是可叠代對象,此外還有更多的對象同樣也是可叠代對象,比如處於打開狀態的files,sockets等等。但凡是可以返回一個 叠代器 的對象都可稱之為可叠代對象,聽起來可能有點困惑,沒關系,可叠代對象與叠代器有一個非常重要的區別。
>>> x=[1,2,3] >>> y=iter(x) >>> z=iter(x) >>> next(y) 1 >>> next(y) 2 >>> next(z) 1 >>> type(x) <class ‘list‘> >>> type(y) <class ‘list_iterator‘>
x 是一個可叠代對象,可叠代對象和容器一樣是一種通俗的叫法,並不是指某種具體的數據類型,list是可叠代對象,dict是可叠代對象,set也是可叠代對象。 y 和 z 是兩個獨立的叠代器,叠代器內部持有一個狀態,該狀態用於記錄當前叠代所在的位置,以方便下次叠代的時候獲取正確的元素。叠代器有一種具體的叠代器類型,比如 list_iterator , set_iterator 。可叠代對象實現了 __iter__ 和 __next__ 方法(python2中是 next 方法,python3是 __next__ 方法),這兩個方法對應內置函數 iter() 和 next() 。 __iter__ 方法返回可叠代對象本身,這使得他既是一個可叠代對象同時也是一個叠代器。
3.一些叠代工具
3.1並行叠代
>>> names=[‘greg‘,‘greg1‘,‘greg2‘] >>> ages=[18,12,13] >>> for i in range(len(names)): print(names[i]+‘ is ‘+str(ages[i])) greg2 is 13 greg2 is 13 greg2 is 13 >>> for n,a in zip(names,ages): print(names[i]+‘ is ‘+str(ages[i])) greg2 is 13 greg2 is 13 greg2 is 13
3.2 編號叠代
list1 = ["這", "是", "一個", "測試"] for index, item in enumerate(list1): print(index, item) 0 這 1 是 2 一個 3 測試
3.2 翻轉和排序叠代
>>> sorted([2,6,3,1,5]) [1, 2, 3, 5, 6] >>> sorted(‘Hello,world!‘) [‘!‘, ‘,‘, ‘H‘, ‘d‘, ‘e‘, ‘l‘, ‘l‘, ‘l‘, ‘o‘, ‘o‘, ‘r‘, ‘w‘] >>> list(reversed(‘Hello,world!‘)) [‘!‘, ‘d‘, ‘l‘, ‘r‘, ‘o‘, ‘w‘, ‘,‘, ‘o‘, ‘l‘, ‘l‘, ‘e‘, ‘H‘] >>> ‘‘.join(reversed(‘Hello,world!‘)) ‘!dlrow,olleH‘
4.叠代器(iterator)
它是一個帶狀態的對象,他能在你調用 next() 方法的時候返回容器中的下一個值,任何實現了 __next__() (python2中實現 next() )方法的對象都是叠代器,至於它是如何實現的這並不重要。
#叠代器,1,有iter方法。2,有next方法 # 可以使用isinstance()判斷一個對象是否是Iterable對象: l=[1,2,3,4] d=iter(l) print(d) #<list_iterator object at 0x000002C34B71C160> # list,tuple,dict,string:iterable print(next(d)) print(next(d)) print(next(d)) print(next(d)) # for循環內部三件事:1,調用可叠代對象iter方法,返回叠代器對象 # 2,不斷調用叠代器對象的next方法 # 3,處理StopIteration,遇到退出 # for i in [1,2,3,4]: # iter([1,2,3,4]) from collections import Iterator,Iterable print(isinstance(2,list))#False l=[1,2,3,4] d=iter(l) print(d) print(isinstance(l,list)) print(isinstance(l,Iterable)) print(isinstance({}, Iterable)) print(isinstance(‘abc‘, Iterable)) print(isinstance((x for x in range(10)), Iterable)) print(isinstance(100, Iterable))#False # 小結 # 凡是可作用於for循環的對象都是Iterable類型; # 凡是可作用於next()函數的對象都是Iterator類型,它們表示一個惰性計算的序列; # 集合數據類型如list、dict、str等是Iterable但不是Iterator,不過可以通過iter()函數獲得一個Iterator對象。 # Python的for循環本質上就是通過不斷調用next()函數實現的,例如: # 首先獲得Iterator對象: it = iter([1, 2, 3, 4, 5]) while True:# 循環: try:# 獲得下一個值: x = next(it) except StopIteration:# 遇到StopIteration就退出循環 break
可以使用叠代器來解決復用可占空間的問題
class Fab(object): def __init__(self, max): self.max = max self.n, self.a, self.b = 0, 0, 1 def __iter__(self): return self def __next__(self): if self.n < self.max: r = self.b self.a, self.b = self.b, self.a + self.b self.n = self.n + 1 return r raise StopIteration() for key in Fab(5): print(key) # 1 # 1 # 2 # 3 # 5
Fab既是一個可叠代對象(因為它實現了 __iter__ 方法),又是一個叠代器(因為實現了 __next__ 方法)。實例變量 self .a 和 self.b 用戶維護叠代器內部的狀態。每次調用 next() 方法的時候做兩件事:
- 為下一次調用 next() 方法修改狀態
- 為當前這次調用生成返回結果
叠代器就像一個懶加載的工廠,等到有人需要的時候才給它生成值返回,沒調用的時候就處於休眠狀態等待下一次調用。
5.從叠代器得到序列
list構造方法顯式將叠代器轉化為列表
class TestIterator: value=0 def __next__(self): self.value +=1 if self.value>10: raise StopIteration return self.value def __iter__(self): return self ti=TestIterator() print(list(ti)) #[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Python:叠代器