每週一個 Python 模組 | itertools
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>)
相關文件: