項目地址:https://git.io/pytipshtml
0x01 介紹了迭代器的概念,即定義了 __iter__()
和 __next__()
方法的對象,或者經過 yield
簡化定義的「可迭代對象」,而在一些函數式編程語言(見 0x02 Python 中的函數式編程)中,相似的迭代器常被用於產生特定格式的列表(或序列),這時的迭代器更像是一種數據結構而非函數(固然在一些函數式編程語言中,這二者並沒有本質差別)。Python 借鑑了 APL, Haskell, and SML
中的某些迭代器的構造方法,並在 itertools
中實現(該模塊是經過 C 實現,源代碼:/Modules/itertoolsmodule.c)。python
itertools
模塊提供了以下三類迭代器構建工具:c++
無限迭代git
整合兩序列迭代github
組合生成器算法
所謂無限(infinite)是指若是你經過 for...in...
的語法對其進行迭代,將陷入無限循環,包括:編程
count(start, [step])
segmentfault
cycle(p)
ruby
repeat(elem [,n])
數據結構
從名字大概能夠猜出它們的用法,既然說是無限迭代,咱們天然不會想要將其全部元素依次迭代取出,而一般是結合 map
/zip
等方法,將其做爲一個取之不盡的數據倉庫,與有限長度的可迭代對象進行組合操做:
from itertools import cycle, count, repeat print(count.__doc__)
count(start=0, step=1) --> count object Return a count object whose .__next__() method returns consecutive values. Equivalent to: def count(firstval=0, step=1): x = firstval while 1: yield x x += step
counter = count() print(next(counter)) print(next(counter)) print(list(map(lambda x, y: x+y, range(10), counter))) odd_counter = map(lambda x: 'Odd#{}'.format(x), count(1, 2)) print(next(odd_counter)) print(next(odd_counter))
0 1 [2, 4, 6, 8, 10, 12, 14, 16, 18, 20] Odd#1 Odd#3
print(cycle.__doc__)
cycle(iterable) --> cycle object Return elements from the iterable until it is exhausted. Then repeat the sequence indefinitely.
cyc = cycle(range(5)) print(list(zip(range(6), cyc))) print(next(cyc)) print(next(cyc))
[(0, 0), (1, 1), (2, 2), (3, 3), (4, 4), (5, 0)] 1 2
print(repeat.__doc__)
repeat(object [,times]) -> create an iterator which returns the object for the specified number of times. If not specified, returns the object endlessly.
print(list(repeat('Py', 3))) rep = repeat('p') print(list(zip(rep, 'y'*3)))
['Py', 'Py', 'Py'] [('p', 'y'), ('p', 'y'), ('p', 'y')]
所謂整合兩序列,是指以兩個有限序列爲輸入,將其整合操做以後返回爲一個迭代器,最爲常見的 zip
函數就屬於這一類別,只不過 zip
是內置函數。這一類別完整的方法包括:
accumulate()
chain()
/chain.from_iterable()
compress()
dropwhile()
/filterfalse()
/takewhile()
groupby()
islice()
starmap()
tee()
zip_longest()
這裏就不對全部的方法一一舉例說明了,若是想要知道某個方法的用法,基本經過 print(method.__doc__)
就能夠了解,畢竟 itertools
模塊只是提供了一種快捷方式,並無隱含什麼深奧的算法。這裏只對下面幾個我以爲比較有趣的方法進行舉例說明。
from itertools import cycle, compress, islice, takewhile, count # 這三個方法(若是使用恰當)能夠限定無限迭代 # print(compress.__doc__) print(list(compress(cycle('PY'), [1, 0, 1, 0]))) # 像操做列表 l[start:stop:step] 同樣操做其它序列 # print(islice.__doc__) print(list(islice(cycle('PY'), 0, 2))) # 限制版的 filter # print(takewhile.__doc__) print(list(takewhile(lambda x: x < 5, count())))
['P', 'P'] ['P', 'Y'] [0, 1, 2, 3, 4]
from itertools import groupby from operator import itemgetter print(groupby.__doc__) for k, g in groupby('AABBC'): print(k, list(g)) db = [dict(name='python', script=True), dict(name='c', script=False), dict(name='c++', script=False), dict(name='ruby', script=True)] keyfunc = itemgetter('script') db2 = sorted(db, key=keyfunc) # sorted by `script' for isScript, langs in groupby(db2, keyfunc): print(', '.join(map(itemgetter('name'), langs)))
groupby(iterable[, keyfunc]) -> create an iterator which returns (key, sub-iterator) grouped by each value of key(value). A ['A', 'A'] B ['B', 'B'] C ['C'] c, c++ python, ruby
from itertools import zip_longest # 內置函數 zip 以較短序列爲基準進行合併, # zip_longest 則以最長序列爲基準,並提供補足參數 fillvalue # Python 2.7 中名爲 izip_longest print(list(zip_longest('ABCD', '123', fillvalue=0)))
[('A', '1'), ('B', '2'), ('C', '3'), ('D', 0)]
關於生成器的排列組合:
product(*iterables, repeat=1)
:兩輸入序列的笛卡爾乘積
permutations(iterable, r=None)
:對輸入序列的徹底排列組合
combinations(iterable, r)
:有序版的排列組合
combinations_with_replacement(iterable, r)
:有序版的笛卡爾乘積
from itertools import product, permutations, combinations, combinations_with_replacement print(list(product(range(2), range(2)))) print(list(product('AB', repeat=2)))
[(0, 0), (0, 1), (1, 0), (1, 1)] [('A', 'A'), ('A', 'B'), ('B', 'A'), ('B', 'B')]
print(list(combinations_with_replacement('AB', 2)))
[('A', 'A'), ('A', 'B'), ('B', 'B')]
# 賽馬問題:4匹馬前2名的排列組合(A^4_2) print(list(permutations('ABCDE', 2)))
[('A', 'B'), ('A', 'C'), ('A', 'D'), ('A', 'E'), ('B', 'A'), ('B', 'C'), ('B', 'D'), ('B', 'E'), ('C', 'A'), ('C', 'B'), ('C', 'D'), ('C', 'E'), ('D', 'A'), ('D', 'B'), ('D', 'C'), ('D', 'E'), ('E', 'A'), ('E', 'B'), ('E', 'C'), ('E', 'D')]
# 綵球問題:4種顏色的球任意抽出2個的顏色組合(C^4_2) print(list(combinations('ABCD', 2)))
[('A', 'B'), ('A', 'C'), ('A', 'D'), ('B', 'C'), ('B', 'D'), ('C', 'D')]
迭代器工具在產生數據的時候將會顯得很是便捷、高效,掌握了這些基本的方法以後,經過簡單的組合就能夠得到更多迭代器工具。
歡迎關注公衆號 PyHub 每日推送