Python 函式建立迭代器以實現高效迴圈
與大多數程式語言一樣,Python 提供 while 和 for 語句來構成迴圈結構。for 語句特別適用於遍歷可迭代物件,例如列表、元組或字串。Python 標準庫中的 itertools 模組定義了更有效和快速的迭代工具。這些迭代器構建塊是類似 Haskell 和 SML 等函數語言程式設計語言中類似工具的 Python 風格實現。
itertools 模組中的函式分為三種類型。
- 無限迭代器
- 有限迭代器
- 組合迭代器
以下函式生成無限序列。
count() − 此函式返回從起始值開始的等間距值的迭代器。該函式可以具有可選的步長值,以該間隔遞增後續值。
>>> from itertools import count >>> for x in count(20): print (x) >>> for x in count(100,10): print (x)
第一個語句將生成從 20 開始的無限序列,第二個語句將生成從 100 開始,步長為 10 的數字。請注意,這些迴圈是無限的,不會自行終止。它們將在按下 Ctrl-C 時終止。
cycle() − 此函式開始返回給定可迭代物件中的每個元素並儲存其副本。一旦元素耗盡,就會返回儲存的副本中的元素,從而形成無限迴圈。
>>> from itertools import cycle >>> for x in cycle("hello"): print (x)
字串中的字元將重複列印,直到發出鍵盤中斷 Ctrl-C。
repeat() − 此函式重複返回物件引數。如果提供了第二個引數“times”,則重複該次數。
>>> from itertools import repeat >>> for x in repeat(1): print (x) >>> for x in repeat('hello', 10): print (x)
第一個迴圈將無限列印 1。第二個迴圈列印“hello”10 次。
以下類別中的函式返回在最短輸入序列上終止的有限迭代器。
accumulate() − 此函式有兩個引數。第一個是可迭代物件(列表、元組或字串)。第二個引數預設為 operator.add()(operator 模組中實現標準加法運算子的函式),但可以是任何其他接收兩個數字引數的函式。
accumulate(sequence, func)
輸入序列的前兩個元素由 func 處理。處理結果是下一次迭代的第一個引數,而 func 的第二個引數是輸入序列中的第三個元素。此過程重複,直到序列耗盡。accumulate 函式返回一個迭代器,其中每個元素都是處理連續元素的累積結果。
在以下示例中,列表中的數字被累加。請注意,預設函式引數是加法運算。
>>> from itertools import accumulate >>> list(accumulate([1,2,3,4,5])) [1, 3, 6, 10, 15]
我們可以將使用者定義的函式作為 accumulate() 函式的第二個引數。
>>> def multiply(x,y): return x*y >>> list(accumulate([1,2,3,4,5], multiply)) [1, 2, 6, 24, 120]
此行為有點類似於內建的 reduce() 函式。reduce() 函式僅返回累積的最終結果,而 accumulate() 構建所有中間結果的迭代器。
chain() − 此函式可以有多個可迭代物件作為引數。它將第一個可迭代物件的每個元素生成到結果迭代器中,並繼續進行下一個,直到可迭代物件引數耗盡。
>>> from itertools import chain >>> list(chain([10,20],'hello',range(4))) [10, 20, 'h', 'e', 'l', 'l', 'o', 0, 1, 2, 3]
dropwhile() − 此函式透過丟棄可迭代物件的元素返回一個迭代器,只要謂詞函式引數返回 true。一旦函式返回 false,所有剩餘的元素都將生成到迭代器中。
>>> from itertools import dropwhile >>> def iseven(x): if x % 2 == 0: return True else: return False >>> list(dropwhile(iseven, [12,90,61,4,15])) [61, 4, 15]
filterfalse() − 此函式透過過濾掉謂詞函式結果為 False 的元素返回一個迭代器。
>>> from itertools import filterfalse >>> def iseven(x): if x % 2 == 0: return True else: return False >>> list(filterfalse(iseven, [12,90,61,4,15])) [61, 15]
islice() − 此函式透過從可迭代物件中選擇某些元素來構建迭代器。選擇標準取決於 start、stop 和 step 引數。選擇從 start 值開始,一直持續到 stop 值。如果 stop 為 None,則一直到可迭代物件的末尾,否則選擇在指定的索引處停止。step 引數預設為 1。元素的選擇按 step 引數遞增。所有引數都不能為負數。
>>> from itertools import islice >>> list(islice(range(10),1,5,2)) [1, 3] >>> list(islice(range(10),0,None,3)) [0, 3, 6, 9] >>> list(islice(range(10),5,None)) [5, 6, 7, 8, 9] >>> list(islice(range(10),5)) [0, 1, 2, 3, 4]
以下函式從可迭代物件生成組合迭代器。
product() − 此函式生成一個迭代器,它是輸入序列中元素的笛卡爾積。這相當於構建巢狀的 for 迴圈,每個迴圈遍歷一個可迭代序列。
在以下示例中,列表推導式技術用於對兩個序列執行兩個巢狀迴圈以構建笛卡爾積。
>>> [[x,y] for x in [1,2,3] for y in ['a','b','c']] [[1, 'a'], [1, 'b'], [1, 'c'], [2, 'a'], [2, 'b'], [2, 'c'], [3, 'a'], [3, 'b'], [3, 'c']]
product() 函式產生類似的結果。
>>> from itertools import product >>> list(product([1,2,3],['a','b','c'])) [(1, 'a'), (1, 'b'), (1, 'c'), (2, 'a'), (2, 'b'), (2, 'c'), (3, 'a'), (3, 'b'), (3, 'c')]
permutations() − 此函式生成輸入可迭代物件中元素的所有可能的排列。每個排列的長度可以作為此函式的第二個引數指定。如果未指定,則長度為 1。
>>> list(permutations(range(1,4),2)) [(1, 2), (1, 3), (2, 1), (2, 3), (3, 1), (3, 2)]
combinations() − 此函式生成輸入可迭代物件中元素的所有可能的組合。每個排列的長度可以作為此函式的第二個引數指定。如果未指定,則長度為 1。
>>> from itertools import combinations >>> list(combinations(range(1,4),2)) [(1, 2), (1, 3), (2, 3)]
本文介紹了 Python 庫的 itertools 模組中定義的各種迭代器工具。