專欄地址:每週一個 Python 模組
同時,也歡迎關注我的微信公眾號 AlwaysBeta,更多精彩內容等你來。
Python 標準庫模組 itertools 提供了很多方便靈活的迭代器工具,熟練的運用可以極大的提高工作效率。
無限迭代器
itertools.count
count(start=0, step=1)
複製程式碼
建立一個迭代器,生成從 n 開始的連續整數,如果忽略 n,則從 0 開始計算。示例:
In [2]: for n in itertools.count():
...: if 100000 < n < 100010:
...: print n
...: if n > 1000000:
...: break
...:
100001
100002
100003
100004
100005
100006
100007
100008
100009
複製程式碼
itertools.cycle
cycle(iterable)
複製程式碼
把傳入的一個序列無限重複下去。示例:
In [6]: count = 0
In [7]: for c in itertools.cycle("AB"):
...: if count > 4:
...: break
...: print c
...: count += 1
...:
A
B
A
B
A
複製程式碼
itertools.repeat
repeat(object [,times])
複製程式碼
建立一個迭代器,重複生成 object,times(如果已提供)指定重複計數,如果未提供 times,將無止盡返回該物件。示例:
In [8]: for x in itertools.repeat("hello world", 5):
...: print x
...:
hello world
hello world
hello world
hello world
hello world
複製程式碼
函式式工具
itertools.ifilter
、itertools.reduce
、itertools.imap
、itertools.izip
與內建函式 filter()
、reduce()
、map()
、zip()
有同樣的功能,只是返回一個迭代器而不是一個序列。在 Python3 中被去掉,因為預設的內建函式就是返回一個迭代器。
itertools.ifilterfalse
ifilterfalse(function or None, sequence)
複製程式碼
python3 為:
filterfalse(function or None, sequence)
複製程式碼
與 filter 類似,但僅生成 sequence 中 function(item) 為 False 的項。示例:
In [25]: for elem in itertools.ifilterfalse(lambda x: x > 5, [2, 3, 5, 6, 7]):
....: print elem
....:
2
3
5
複製程式碼
itertools.izip_longest
izip_longest(iter1 [,iter2 [...]], [fillvalue=None])
複製程式碼
Python3 為:
zip_longest(iter1 [,iter2 [...]], [fillvalue=None])
複製程式碼
與 zip 類似,但不同的是它會把最長的 iter 迭代完才結束,其他 iter 如果有缺失值則用 fillvalue 填充。示例:
In [33]: for item in itertools.izip_longest('abcd', '12', fillvalue='-'):
....: print item
....:
('a', '1')
('b', '2')
('c', '-')
('d', '-')
複製程式碼
itertools.starmap
starmap(function, sequence)
複製程式碼
對序列 sequence 的每個元素作為 function 的引數列表執行,即 function(*item)
, 返回執行結果的迭代器。只有當 iterable 生成的項適用於這種呼叫函式的方式時,此函式才有效。示例:
In [35]: seq = [(0, 5), (1, 6), (2, 7), (3, 3), (3, 8), (4, 9)]
In [36]: for item in itertools.starmap(lambda x,y:(x, y, x*y), seq):
...: print "%d * %d = %d" % item
...:
0 * 5 = 0
1 * 6 = 6
2 * 7 = 14
3 * 3 = 9
3 * 8 = 24
4 * 9 = 36
複製程式碼
itertools.dropwhile
dropwhile(predicate, iterable)
複製程式碼
建立一個迭代器,只要函式 predicate(item) 為 True,就丟棄 iterable 中的項,如果 predicate 返回 False,就會生成 iterable 中的項和所有後續項。即在條件為false之後的第一次, 返回迭代器中剩下來的項。示例:
In [41]: for item in itertools.dropwhile(lambda x: x<1, [ -1, 0, 1, 2, 3, 4, 1, -2 ]):
...: print item
...:
1
2
3
4
1
-2
複製程式碼
itertools.takewhile
takewhile(predicate, iterable)
複製程式碼
與 dropwhile 相反。建立一個迭代器,生成 iterable 中 predicate(item) 為 True 的項,只要 predicate 計算為 False,迭代就會立即停止。示例:
In [28]: for item in itertools.takewhile(lambda x: x < 2, [ -1, 0, 1, 2, 3, 4, 1, -2 ]):
....: print item
....:
-1
0
1
複製程式碼
組合工具
itertools.chain
chain(*iterables)
複製程式碼
把一組迭代物件串聯起來,形成一個更大的迭代器。示例:
In [9]: for c in itertools.chain('ABC', 'XYZ'):
...: print c
...:
A
B
C
X
Y
Z
複製程式碼
itertools.product
product(*iterables, repeat=1)
複製程式碼
建立一個迭代器,生成多個迭代器集合的笛卡爾積,repeat 引數用於指定重複生成序列的次數。示例:
In [6]: for elem in itertools.product((1, 2), ('a', 'b')):
...: print elem
...:
(1, 'a')
(1, 'b')
(2, 'a')
(2, 'b')
In [7]: for elem in itertools.product((1, 2), ('a', 'b'), repeat=2):
...: print elem
...:
(1, 'a', 1, 'a')
(1, 'a', 1, 'b')
(1, 'a', 2, 'a')
(1, 'a', 2, 'b')
(1, 'b', 1, 'a')
(1, 'b', 1, 'b')
(1, 'b', 2, 'a')
(1, 'b', 2, 'b')
(2, 'a', 1, 'a')
(2, 'a', 1, 'b')
(2, 'a', 2, 'a')
(2, 'a', 2, 'b')
(2, 'b', 1, 'a')
(2, 'b', 1, 'b')
(2, 'b', 2, 'a')
(2, 'b', 2, 'b')
複製程式碼
itertools.permutations
permutations(iterable[, r])
複製程式碼
返回 iterable 中任意取 r 個元素做排列的元組的迭代器,如果不指定 r,那麼序列的長度與 iterable 中的專案數量相同。示例:
In [7]: for elem in itertools.permutations('abc', 2):
...: print elem
...:
('a', 'b')
('a', 'c')
('b', 'a')
('b', 'c')
('c', 'a')
('c', 'b')
In [8]: for elem in itertools.permutations('abc'):
...: print elem
...:
('a', 'b', 'c')
('a', 'c', 'b')
('b', 'a', 'c')
('b', 'c', 'a')
('c', 'a', 'b')
('c', 'b', 'a')
複製程式碼
itertools.combinations
combinations(iterable, r)
複製程式碼
與 permutations 類似,但組合不分順序,即如果 iterable 為 "abc",r 為 2 時,ab 和 ba 則視為重複,此時只放回 ab. 示例:
In [10]: for elem in itertools.combinations('abc', 2):
....: print elem
....:
('a', 'b')
('a', 'c')
('b', 'c')
複製程式碼
itertools.combinations_with_replacement
combinations_with_replacement(iterable, r)
複製程式碼
與 combinations 類似,但允許重複值,即如果 iterable 為 "abc",r 為 2 時,會多出 aa, bb, cc. 示例:
In [14]: for elem in itertools.combinations_with_replacement('abc', 2):
....: print elem
....:
('a', 'a')
('a', 'b')
('a', 'c')
('b', 'b')
('b', 'c')
('c', 'c')
複製程式碼
其他工具
itertools.compress
compress(data, selectors)
複製程式碼
相當於 bool 選取,只有當 selectors 對應位置的元素為 true 時,才保留 data 中相應位置的元素,否則去除。示例:
In [39]: list(itertools.compress('abcdef', [1, 1, 0, 1, 0, 1]))
Out[39]: ['a', 'b', 'd', 'f']
In [40]: list(itertools.compress('abcdef', [True, False, True]))
Out[40]: ['a', 'c']
複製程式碼
itertools.groupby
groupby(iterable[, keyfunc])
複製程式碼
對 iterable 中的元素進行分組。keyfunc 是分組函式,用於對 iterable 的連續項進行分組,如果不指定,則預設對 iterable 中的連續相同項進行分組,返回一個 (key, sub-iterator) 的迭代器。示例:
In [45]: for key, value_iter in itertools.groupby('aaabbbaaccd'):
....: print key, list(value_iter)
....:
a ['a', 'a', 'a']
b ['b', 'b', 'b']
a ['a', 'a']
c ['c', 'c']
d ['d']
In [48]: data = ['a', 'bb', 'cc', 'ddd', 'eee', 'f']
In [49]: for key, value_iter in itertools.groupby(data, len):
....: print key, list(value_iter)
....:
1 ['a']
2 ['bb', 'cc']
3 ['ddd', 'eee']
1 ['f']
複製程式碼
注意,注意,注意:必須先排序後才能分組,因為 groupby
是通過比較相鄰元素來分組的。可以看第二個例子,因為 a 和 f 沒有排在一起,所以最後沒有分組到同一個列表中。
itertools.islice
islice(iterable, [start,] stop [, step])
複製程式碼
切片選擇,start 是開始索引,stop 是結束索引,step 是步長,start 和 step 可選。示例:
In [52]: list(itertools.islice([10, 6, 2, 8, 1, 3, 9], 5))
Out[52]: [10, 6, 2, 8, 1]
In [53]: list(itertools.islice(itertools.count(), 6))
Out[53]: [0, 1, 2, 3, 4, 5]
In [54]: list(itertools.islice(itertools.count(), 3, 10))
Out[54]: [3, 4, 5, 6, 7, 8, 9]
In [55]: list(itertools.islice(itertools.count(), 3, 10, 2))
Out[55]: [3, 5, 7, 9]
複製程式碼
itertools.tee
tee(iterable, n=2)
複製程式碼
從 iterable 建立 n 個獨立的迭代器,以元組的形式返回。示例:
In [57]: itertools.tee("abcedf")
Out[57]: (<itertools.tee at 0x7fed7b8f59e0>, <itertools.tee at 0x7fed7b8f56c8>)
In [58]: iter1, iter2 = itertools.tee("abcedf")
In [59]: list(iter1)
Out[59]: ['a', 'b', 'c', 'e', 'd', 'f']
In [60]: list(iter2)
Out[60]: ['a', 'b', 'c', 'e', 'd', 'f']
In [61]: itertools.tee("abcedf", 3)
Out[61]:
(<itertools.tee at 0x7fed7b8f5cf8>,
<itertools.tee at 0x7fed7b8f5cb0>,
<itertools.tee at 0x7fed7b8f5b00>)
複製程式碼
相關文件: