itertools 模塊提供了一系列函數集,用來操作序列數據類型。
itertools 模塊的靈感(inspired)來自面向函數編程(functional programming languages)的語言,如:Clojure、Haskell、APL 和 SML。他們執行的速度很快而且內存使用更有效率(efficiently),經常結合在一起用來解釋複雜的基於迭代器的算法。
基於迭代器的代碼提供了較好的內存消耗特性(memory consumption characteristics)。
因為數據不是一次性而是根據需要才生成的,所有的數據不用一下子佔據所有的內存。
這種懶惰(lazy)的特性提供了較好的性能。
下面是 itertools 模塊的一些例子。
合併、分割迭代器 Merging and Splitting Iterators
chain() 方法接收多個迭代器作為參數,返回一個單獨的迭代器,包含所有的數據。
執行:
chain() 方法合併多個迭代器,而不用一下子構造一個大的數據集。
chain.from_iterable() 方法和 chain() 不同,它只接收一個參數 iterables。
懶惰(lazy)的生成下一個值。
執行:
內置方法 zip() 合併多個迭代器的元素到元組列表。
執行:
如果迭代器的長度不一致,zip() 不會處理多餘的數據。
兩個序列,一個長度是4,另一個是2,則最終的結果只生成兩個元組。
zip_longest() 方法會處理所有的數據。
執行:
默認,zip_longest() 方法使用 None 補齊不足的值。
islice() 方法從一個迭代器,按照索引返回選中的值。
執行:
islice() 方法接收的參數和序列的切片是一樣的:start, stop 和 step。 參數 start 和 step 是可選的。
tee() 方法從一個迭代器返回2個迭代器。
執行:
tee() 方法類似於 Unix 的 tee 命令(從輸入獲取到數據,寫入到輸出和文件),從 tee() 方法返回的相同的數據可
用到多種同時處理數據的算法中。
tee() 返回的迭代器和他接收的參數共用一個迭代器。
執行:
轉變迭代的值
內置函數 map() 輸入一個迭代器,返回被函數操作後的新的迭代器。
執行:
第一個例子中,把迭代器 range(5) 中每個值乘以2,返回新迭代器。第二個例子中,兩個迭代器的值按次序
應用函數 multi() 然後返回包含新值的迭代器。
starmap() 和 map() 函數類似,只不過它是從一個迭代器,把每個值解析到一個函數的參數然後返回數據。
執行:
生成新值
count() 方法返回一個迭代器,無限生成連續不斷(consecutive)的整數值。第一個值是0,也可以傳入第一個參數作為起始值。
執行:
這個例子中,由於 count() 產生的值是無限的,使用 zip() 函數限制一下數量,合併前3個值,起始為1。
count() 函數還有一個可選的參數 step,它可以是任何數字類型的,例如使用 Fraction。
執行:
這個例子,使用的分數 Fraction,count() 方法起始值為 1/3,每次加 1/3。
repeat() 方法返回一個迭代器,使用相同的值重複一定的次數。
執行:
返回的迭代器包含了3個字符串 hello。
和 zip() 函數結合使用。
執行:
和 map() 函數結合使用。
執行:
過濾 Filtering
dropwhile() 函數會一直過濾元素,直到它第一次遇到函數返回為 False,然後返回剩下的值。
執行:
這個例子中,過濾了1和2,因為他們判斷小於3為 True,到 3 的時候條件為 False,所以從 3 往後的元素都返回。
takewhile() 正好和 dropwhile() 相反,它返回一個迭代器,只要條件是 True就返回,直到返回 False 的情況。
執行:
take() 函數返回 False 的時候, takewhile() 就不往後處理數據了。
filterfalse() 方法返回一個迭代器,只返回驗證為 False 的數據。
執行:
compress() 方法不是用函數過濾數據,而是依據另一個迭代器返回數據。
執行:
本例中,根據 test_iter 迭代器過濾 range(1, 10) 的數據,test_iter 是 cycle() 方法生成的一個無限
數據的迭代器,值為 False,True 兩個值組成,無限循環。如下:
test_iter: False,True,False,True,False,True …
range(1,10): 1 2 3 4 5 6 …
返回 range(1,10) 和 test_iter 位置相同值為 True的索引值:2,4,6,8。
分組 Grouping Data
groupby() 方法返回一個迭代器,分組由公共的鍵(key)組成的值。鍵(key)通常是迭代器中元素的一部分,
就像內置的函數 sort() 的參數 key 一樣。
使用 groupby() 方法分組的數據,相同的分組鍵(key)應該相鄰才有效。
執行:
本例中,使用每個元組中的第一個元素分組,使用的是 operator 模塊的 itemgetter() 方法獲取指定索引
處的值。
groupby() 返回的對象,包含分組鍵(key)和一個子迭代器,子迭代器包含所有的分組。
合併輸入值
accumulate() 方法接收一個序列,累加第n個值和第n+1個值,返回生成的值的迭代器。
accumulate() 返回一個新迭代器,每個新生成的值都是原來迭代器當前位置和之前所有元素累積之和。
accumulate() 方法接收可選的第二個函數參數,根據兩個值自定義返回結果。
執行:
product() 方法,根據多個輸入參數,返回他們的笛卡爾乘積(Cartesian product)。
執行:
product() 方法返回的是一個元組列表,每個元組分別按順序從輸入的迭代器中取值,直到每個迭代器的最後
一個元素。
permutations() 方法返回輸入的迭代器的值組成的所有排列,還可以指定排列的長度。
執行:
show() 函數按生成的組合開頭字母相同的為一行,打印所有不同的組合。permutations() 方法接收參數 r
指定生成的組合的長度。
從上面輸出可以看到, permutations() 方法返回的元素有相同的,例如 ab 和 ba值相同,都是 a 和 b,只是順序不一樣,在數學上叫排列。
可以使用 combinations() 去掉相同的元素,只是返回不同的組合。
執行:
和 permutations() 相比, combinations() 去掉了重複的值。注意,參數 r 是必須要傳的。
combinations() 不包含相同元素的情況,例如 aa,可以使用 combinations_with_replacement() 方法。
執行:
閱讀更多 趣喜歡編程 的文章