上一篇 ( 羅列 Python 標準庫中的生成器函數(shù) (2) ) 我們列舉了 用于合并多個可迭代對象的生成器函數(shù) ,接下來我們繼續(xù)列舉標準庫中剩下的生成器函數(shù)
有些生成器函數(shù)會從一個元素中產(chǎn)出多個值,擴展輸入的可迭代對象,如下所示。
4、把輸入的各個元素擴展成多個輸出元素的生成器函數(shù)
| 模塊 | 函數(shù) | 說明 |
|---|---|---|
| itertools | combinations(it, out_len) | 把 it 產(chǎn)出的 out_len 個元素組合在一起,然后產(chǎn)出 |
| itertools | combinations_with_replacement(it,out_len) | 把 it 產(chǎn)出的 out_len 個元素組合在一起,然后產(chǎn)出,包含相同元素的組合 |
| itertools | count(start=0, step=1) | 從 start 開始不斷產(chǎn)出數(shù)字,按step 指定的步幅增加 |
| itertools | cycle(it) | 從 it 中產(chǎn)出各個元素,存儲各個元素的副本,然后按順序重復(fù)不斷地產(chǎn)出各個元素 |
| itertools | permutations(it, out_len=None) | 把 out_len 個 it 產(chǎn)出的元素排列在一起,然后產(chǎn)出這些排列;out_len的默認值等于 len(list(it)) |
| itertools | repeat(item, [times]) | 重復(fù)不斷地產(chǎn)出指定的元素,除非提供 times,指定次數(shù) |
itertools 模塊中的 count 和 repeat 函數(shù)返回的生成器“無中生有”:這兩個函數(shù)都不接受可迭代的對象作為輸入。生成器函數(shù)第一篇中見過itertools.count 函數(shù)。cycle 生成器會備份輸入的可迭代對象,然后重復(fù)產(chǎn)出對象中的元素。如下演示 count、repeat 和 cycle的用法(count()生成器函數(shù)在第一篇已經(jīng)講過了,此處按照分類再次演示):
>>> ct = itertools.count() # 1
>>> next(ct) # 2
0
>>> next(ct), next(ct), next(ct) # 3
(1, 2, 3)
>>> list(itertools.islice(itertools.count(1, .3), 3)) # 4
[1, 1.3, 1.6]
>>> cy = itertools.cycle('ABC') # 5
>>> next(cy)
'A'
>>> list(itertools.islice(cy, 7)) # 6
['B', 'C', 'A', 'B', 'C', 'A', 'B']
>>> rp = itertools.repeat(7) # 7
>>> next(rp), next(rp)
(7, 7)
>>> list(itertools.repeat(8, 4)) # 8
[8, 8, 8, 8]
>>> list(map(operator.mul, range(11), itertools.repeat(5))) # 9
[0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50]
1、使用 count 函數(shù)構(gòu)建 ct 生成器。
2、獲取 ct 中的第一個元素。
3、不能使用 ct 構(gòu)建列表,因為 ct 是無窮的,所以我獲取接下來的 3個元素。
4、如果使用 islice 或 takewhile 函數(shù)做了限制,可以從 count 生成器中構(gòu)建列表。
5、使用 'ABC' 構(gòu)建一個 cycle 生成器,然后獲取第一個元素——'A'。
6、只有受到 islice 函數(shù)的限制,才能構(gòu)建列表;這里獲取接下來的 7個元素。
7、構(gòu)建一個 repeat 生成器,始終產(chǎn)出數(shù)字 7。
8、傳入 times 參數(shù)可以限制 repeat 生成器生成的元素數(shù)量:這里會生成 4 次數(shù)字 8。
9、repeat 函數(shù)的常見用途:為 map 函數(shù)提供固定參數(shù),這里提供的是乘數(shù) 5。
在 itertools 模塊的文檔中(https://docs.python.org/3/library/itertools.html), combinations、combinations_with_replacement和 permutations 生成器函數(shù),連同 product 函數(shù),稱為組合學生成器(combinatoric generator)。itertools.product 函數(shù)和其余的組合學函數(shù)有緊密的聯(lián)系,如以下示例所示:
>>> list(itertools.combinations('ABC', 2)) # 1
[('A', 'B'), ('A', 'C'), ('B', 'C')]
>>> list(itertools.combinations_with_replacement('ABC', 2)) # 2
[('A', 'A'), ('A', 'B'), ('A', 'C'), ('B', 'B'), ('B', 'C'), ('C', 'C')]
>>> list(itertools.permutations('ABC', 2)) # 3
[('A', 'B'), ('A', 'C'), ('B', 'A'), ('B', 'C'), ('C', 'A'), ('C', 'B')]
>>> list(itertools.product('ABC', repeat=2)) # 4
[('A', 'A'), ('A', 'B'), ('A', 'C'), ('B', 'A'), ('B', 'B'), ('B', 'C'),
('C', 'A'), ('C', 'B'), ('C', 'C')]
1、'ABC' 中每兩個元素(len()==2)的各種組合;在生成的元組中,
元素的順序無關(guān)緊要(可以視作集合)。
2、'ABC' 中每兩個元素(len()==2)的各種組合,包括相同元素的組
合。
3、'ABC' 中每兩個元素(len()==2)的各種排列;在生成的元組中,
元素的順序有重要意義。
4、'ABC' 和 'ABC'(repeat=2 的效果)的笛卡兒積。
接下來要說的的最后一組生成器函數(shù)用于產(chǎn)出輸入的可迭代對象中的全部元素,不過會以某種方式重新排列。其中有兩個函數(shù)會返回多個生成器,分別是 itertools.groupby 和 itertools.tee。這一組里的另一個生成器函數(shù),內(nèi)置的 reversed 函數(shù),是列舉的所述函數(shù)中唯一一個不接受可迭代的對象,而只接受序列為參數(shù)的函數(shù)。這在情理之中,因為reversed 函數(shù)從后向前產(chǎn)出元素,而只有序列的長度已知時才能工作。不過,這個函數(shù)會按需產(chǎn)出各個元素,因此無需創(chuàng)建反轉(zhuǎn)的副本。另外 itertools.product 函數(shù)劃分為用于合并的生成器,已經(jīng)列在了表3、用于合并多個可迭代對象的生成器函數(shù)中,因為那一組函數(shù)都處理多個可迭代的對象,而下面所列的的生成器最多只能接受一個可迭代的對象
4、用于重新排列元素的生成器函數(shù)
| 模塊 | 函數(shù) | 說明 |
|---|---|---|
| itertools | groupby(it,key=None) | 產(chǎn)出由兩個元素組成的元素,形式為 (key,group),其中 key 是分組標準,group 是生成器,用于產(chǎn)出分組里的元素 |
| (內(nèi)置) | reversed(seq) | 從后向前,倒序產(chǎn)出 seq 中的元素;seq 必須是序列,或者是實現(xiàn)了 reversed 特殊方法的對象 |
| itertools | tee(it, n=2) | 產(chǎn)出一個由 n 個生成器組成的元組,每個生成器用于單獨產(chǎn)出輸入的可迭代對象中的元素 |
以下先演示 itertools.groupby 函數(shù)和內(nèi)置的 reversed 函數(shù)的用法。注意,itertools.groupby 假定輸入的可迭代對象要使用分組標準排序;即使不排序,至少也要使用指定的標準分組各個元素。
>>> list(itertools.groupby('LLLLAAGGG')) # 1
[('L', <itertools._grouper object at 0x102227cc0>),
('A', <itertools._grouper object at 0x102227b38>),
('G', <itertools._grouper object at 0x102227b70>)]
>>> for char, group in itertools.groupby('LLLLAAAGG'): # 2
... print(char, '->', list(group))
...
L -> ['L', 'L', 'L', 'L']
A -> ['A', 'A',]
G -> ['G', 'G', 'G']
>>> animals = ['duck', 'eagle', 'rat', 'giraffe', 'bear',
... 'bat', 'dolphin', 'shark', 'lion']
>>> animals.sort(key=len) # 3
>>> animals
['rat', 'bat', 'duck', 'bear', 'lion', 'eagle', 'shark',
'giraffe', 'dolphin']
>>> for length, group in itertools.groupby(animals, len): # 4
... print(length, '->', list(group))
...
3 -> ['rat', 'bat']
4 -> ['duck', 'bear', 'lion']
5 -> ['eagle', 'shark']
7 -> ['giraffe', 'dolphin']
>>> for length, group in itertools.groupby(reversed(animals), len): # 5
... print(length, '->', list(group))
...
7 -> ['dolphin', 'giraffe']
5 -> ['shark', 'eagle']
4 -> ['lion', 'bear', 'duck']
3 -> ['bat', 'rat']
>>>
1、groupby 函數(shù)產(chǎn)出 (key, group_generator) 這種形式的元組。
2、處理 groupby 函數(shù)返回的生成器要嵌套迭代:這里在外層使用 for循環(huán),內(nèi)層使用列表推導(dǎo)。
3、為了使用 groupby 函數(shù),要排序輸入;這里按照單詞的長度排序。
4、再次遍歷 key 和 group 值對,把 key 顯示出來,并把 group 擴展成列表。
5、這里使用 reverse 生成器從右向左迭代 animals。
這一組里的最后一個生成器函數(shù)是 iterator.tee,這個函數(shù)只有一個作用:從輸入的一個可迭代對象中產(chǎn)出多個生成器,每個生成器都可以產(chǎn)出輸入的各個元素。產(chǎn)出的生成器可以單獨使用,如以下示例所示。
[<itertools._tee object at 0x10222abc8>, <itertools._tee object at 0x10222ac08>]
>>> g1, g2 = itertools.tee('ABC')
>>> next(g1)
'A'
>>> next(g2)
'A'
>>> next(g2)
'B'
>>> list(g1)
['B', 'C']
>>> list(g2)
['C']
>>> list(zip(*itertools.tee('ABC')))
[('A', 'A'), ('B', 'B'), ('C', 'C')]
在三篇介紹生成器函數(shù)示例中多次把不同的生成器函數(shù)組合在一起使用。其實這就是這些函數(shù)的優(yōu)秀特性:這些函數(shù)的參數(shù)都是生成器,而返回的結(jié)果也是生成器,因此能以很多不同的方式結(jié)合在一起使用