1. 程式人生 > >每週一個 Python 模組 | itertools

每週一個 Python 模組 | itertools

系列文章列表:
每週一個 Python 模組 | functools

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.ifilteritertools.reduce
itertools.imapitertools.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>)
複製程式碼



相關文件:

blog.konghy.cn/2017/04/25/…

juejin.im/post/5af562…