標準庫中的生成器函數

用於過濾的生成器函數

一、itertools.compress(it, selector_it)ide

並行處理兩個可迭代對象;若是select_it中的元素是真值,產出it中對應的元素函數

二、itertools.dropwhile(predicate, it)測試

處理it,跳過predicate的計算結果爲真值的元素,而後產出剩下的各個元素ui

三、filter(predicate, it)spa

把it中的各個元素傳給predicate,若是predicate(item)返回真值,那麼產生對應的元素;若是predicate是None,那麼只產出真值元素。code

四、itertools.filterfalse(predicate, it)協程

與filter函數的做用相似,不過predicate的邏輯是相反的,predicate返回假值時產生對應的元素對象

五、itertools.islice(it, stop)或islice(it, start, stop, step=1)blog

產出的it切片,做用相似於s[: stop]或s[start: stop: step],不過it能夠是任何可迭代的對象,並且這個函數實現的是惰性操做ip

六、itertools.takewhile(predicate, it)

predicate返回真值時產出對應的元素,而後馬上中止,再也不繼續檢查

 1 def vowel(c):
 2     return c.lower() in 'aeiou'
 3 
 4 
 5 print(list(filter(vowel, 'Aardvark')))
 6 # ['A', 'a', 'a']
 7 import itertools
 8 
 9 print(list(itertools.filterfalse(vowel, 'Aardvark')))
10 # ['r', 'd', 'v', 'r', 'k']
11 print(list(itertools.dropwhile(vowel, 'Aardvark')))
12 # ['r', 'd', 'v', 'a', 'r', 'k']
13 print(list(itertools.takewhile(vowel, 'Aardvark')))
14 # ['A', 'a']
15 print(list(itertools.islice('Aardvark', 4)))
16 # ['A', 'a', 'r', 'd']
17 print(list(itertools.islice('Aardvark', 4, 7)))
18 # ['v', 'a', 'r']
19 print(list(itertools.islice('Aardvark', 1, 7, 2)))
20 # ['a', 'd', 'a']
測試代碼

 

用於映射的生成器函數

一、itertools.accumulate(it, [func])

默認產出累積的總和,若是提供了func,那麼把前兩個元素傳給它,而後把計算結果和下一個元素傳給它,以此類推,最後產出結果

二、enumerate(iterable, start=0)

產生由兩個元素組成的元組,結構是(index, item),其中index從start開始計數,item則從iterable中獲取

三、map(func, it1, [it2, ..., itN])

把it中的各個元素傳給func,產出結果;若是傳入N個可迭代的對象,那麼func必須接收N個參數,並且要並行處理各個可迭代對象

四、itertools.starmap(func, it)

把it中的各個元素傳給func,產出結果;輸入的可迭代對象應該產出可迭代的元素iit,而後以func(*iit)這種形態調用func

 1 sample = [5, 4, 2, 8, 7, 6, 3, 0, 9, 1]
 2 
 3 import itertools
 4 
 5 print(list(itertools.accumulate(sample)))
 6 # [5, 9, 11, 19, 26, 32, 35, 35, 44, 45]
 7 print(list(itertools.accumulate(sample, min)))
 8 # [5, 4, 2, 2, 2, 2, 2, 0, 0, 0]
 9 print(list(itertools.accumulate(sample, max)))
10 # [5, 5, 5, 8, 8, 8, 8, 8, 9, 9]
11 
12 import operator
13 print(list(itertools.accumulate(sample, operator.mul)))
14 # [5, 20, 40, 320, 2240, 13440, 40320, 0, 0, 0]
15 print(list(itertools.accumulate(range(1, 11), operator.mul)))
16 # [1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800]
accumulate生成器函數
 1 print(list(enumerate('albatroz', 1)))
 2 # [(1, 'a'), (2, 'l'), (3, 'b'), (4, 'a'), (5, 't'), (6, 'r'), (7, 'o'), (8, 'z')]
 3 import operator
 4 
 5 print(list(map(operator.mul, range(11), range(11))))
 6 # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
 7 print(list(map(operator.mul, range(11), [2, 4, 8])))
 8 # [0, 4, 16]
 9 print(list(map(lambda a, b: (a, b), range(11), [2, 4, 8])))
10 # [(0, 2), (1, 4), (2, 8)]
11 import itertools
12 
13 print(list(itertools.starmap(operator.mul, enumerate('albatroz', 1))))
14 # ['a', 'll', 'bbb', 'aaaa', 'ttttt', 'rrrrrr', 'ooooooo', 'zzzzzzzz']
15 sample = [5, 4, 2, 8, 7, 6, 3, 0, 9, 1]
16 
17 print(list(itertools.starmap(lambda a, b: b/a, enumerate(itertools.accumulate(sample), 1))))
18 # [5.0, 4.5, 3.6666666666666665, 4.75, 5.2, 5.333333333333333, 5.0, 4.375, 4.888888888888889, 4.5]
測試代碼

 

合併多個可迭代對象的生成器函數

一、itertools.chain(it1, ..., itN)

先產出it1中的全部元素,而後產生it2中的全部元素,以此類推,無縫鏈接在一塊兒

二、itertools.chain.from_iterable(it)

產生it生成的各個可迭代對象中的元素,一個接一個,無縫鏈接在一塊兒;it應該產出可迭代的元素,列入可迭代的對象列表

三、itertools.product(it1, ..., itN, repeat=1)

計算笛卡爾積:從輸入的各個可迭代對象中獲取元素,產出由N個元素組成的元組,與嵌套的for循環效果同樣;repeat指明重複處理多少次輸入的可迭代對象

四、zip(it1, ..., itN)

並行從輸入的各個可迭代對象中獲取元素,產出由N個元素組成的元組,只要有一個可迭代的對象到頭了,就默默地中止。

五、itertools.zip_longest(it1, itN, fillvalue=None)

並行從輸入的各個可迭代對象中獲取元素,產出N個元素組成的元組,等到最長的可迭代對象到頭後中止,空缺的值使用fillvalue填充

 1 import itertools
 2 print(list(itertools.chain('ABC', range(2))))
 3 # ['A', 'B', 'C', 0, 1]
 4 print(list(itertools.chain(enumerate('ABC'))))
 5 # [(0, 'A'), (1, 'B'), (2, 'C')]
 6 print(list(itertools.chain.from_iterable(enumerate('ABC'))))
 7 # [0, 'A', 1, 'B', 2, 'C']
 8 print(list(zip('ABC', range(5))))
 9 # [('A', 0), ('B', 1), ('C', 2)]
10 print(list(zip('ABC', range(5), [10, 20, 30, 40])))
11 # [('A', 0, 10), ('B', 1, 20), ('C', 2, 30)]
12 print(list(itertools.zip_longest('ABC', range(5))))
13 # [('A', 0), ('B', 1), ('C', 2), (None, 3), (None, 4)]
14 print(list(itertools.zip_longest('ABC', range(5), fillvalue='?')))
15 # [('A', 0), ('B', 1), ('C', 2), ('?', 3), ('?', 4)]
演示用於合併的生成器函數
 1 import itertools
 2 
 3 print(list(itertools.product('ABC', range(2))))
 4 # [('A', 0), ('A', 1), ('B', 0), ('B', 1), ('C', 0), ('C', 1)]
 5 suits = 'spades hearts diamonds clubs'.split()
 6 
 7 print(list(itertools.product('AK', suits)))
 8 # [('A', 'spades'), ('A', 'hearts'), ('A', 'diamonds'), ('A', 'clubs'), ('K', 'spades'), ('K', 'hearts'), ('K', 'diamonds'), ('K', 'clubs')]
 9 print(list(itertools.product('ABC')))
10 # [('A',), ('B',), ('C',)]
11 print(list(itertools.product('ABC', repeat=2)))
12 # [('A', 'A'), ('A', 'B'), ('A', 'C'), ('B', 'A'), ('B', 'B'), ('B', 'C'), ('C', 'A'), ('C', 'B'), ('C', 'C')]
13 print(list(itertools.product(range(2), repeat=3)))
14 # [(0, 0, 0), (0, 0, 1), (0, 1, 0), (0, 1, 1), (1, 0, 0), (1, 0, 1), (1, 1, 0), (1, 1, 1)]
15 rows = itertools.product(range(2), repeat=3)
16 
17 for row in rows:
18     print(row)
19 # (0, 0, 0)
20 # (0, 0, 1)
21 # (0, 1, 0)
22 # (0, 1, 1)
23 # (1, 0, 0)
24 # (1, 0, 1)
25 # (1, 1, 0)
26 # (1, 1, 1)
product生成器函數

 

把輸入的各個元素擴展成多個輸出元素的生成器函數

一、itertools.combinations(it, out_len)

把it產生的out_len個元素組合在一塊兒,而後產出

二、itertools.combinations_with_replacement(it, out_len)

把it產出的out_len個元素組合在一塊兒,而後產出包含相同元素的組合

三、itertools.count(start=0, step=1)

從start開始不斷產出數字,按step指定的步幅增長

四、itertools.cycle(it)

從it中產出各個元素,村粗各個元素的副本,而後按順序重複不斷地產出各個元素

五、itertools.permutations(it, out_len=None)

把out_len個it產出的元素排列到一塊兒,而後產出這些排列;out_len的默認值等於len(list(it))

六、itertools.repeat(item, [times])

重複不斷地產出指定的元素,除非提供times,指定次數

 1 import itertools, operator
 2 
 3 
 4 ct = itertools.count()
 5 print(next(ct))
 6 # 0
 7 print(next(ct), next(ct), next(ct))
 8 # 1 2 3
 9 print(list(itertools.islice(itertools.count(1, .3), 3)))
10 # [1, 1.3, 1.6]
11 cy = itertools.cycle('ABC')
12 print(next(cy))
13 # A
14 print(list(itertools.islice(cy, 7)))
15 # ['B', 'C', 'A', 'B', 'C', 'A', 'B']
16 rp = itertools.repeat(7)
17 print(next(rp), next(rp))
18 # 7 7
19 print(list(itertools.repeat(8, 4)))
20 # [8, 8, 8, 8]
21 print(list(map(operator.mul, range(11), itertools.repeat(5))))
22 # [0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50]
count、repeat和cycle的用法
 1 import itertools
 2 
 3 print(list(itertools.combinations('ABC', 2)))
 4 # [('A', 'B'), ('A', 'C'), ('B', 'C')]
 5 print(list(itertools.combinations_with_replacement('ABC', 2)))
 6 # [('A', 'A'), ('A', 'B'), ('A', 'C'), ('B', 'B'), ('B', 'C'), ('C', 'C')]
 7 print(list(itertools.permutations('ABC', 2)))
 8 # [('A', 'B'), ('A', 'C'), ('B', 'A'), ('B', 'C'), ('C', 'A'), ('C', 'B')]
 9 print(list(itertools.product('ABC',repeat=2)))
10 # [('A', 'A'), ('A', 'B'), ('A', 'C'), ('B', 'A'), ('B', 'B'), ('B', 'C'), ('C', 'A'), ('C', 'B'), ('C', 'C')]
組合學生成器函數會輸入的各個元素中產生多個值

 

用於從新排列元素的生成器函數

一、itertools.groupby(it, key=None)

產生由兩個元素組成的元素,形式爲(key, group),其中能夠是分組標準,group是生成器,用於產出分組裏的元素

二、reversed(seq)

從後往前,倒序產出seq中的元素;seq必須是序列,或者是實現了__reversed__特殊方法的對象

三、itertools.tee(it, n=2)

產出一個由n個生成器組成的元組,每一個生成器用於單獨產出輸入的可迭代對象中的元素

 1 import itertools
 2 
 3 print(list(itertools.groupby('LLLLAAGGG')))
 4 # [('L', <itertools._grouper object at 0x10dcf2208>), 
 5 # ('A', <itertools._grouper object at 0x10dcf2240>), 
 6 # ('G', <itertools._grouper object at 0x10dcf2198>)]
 7 
 8 for char, group in itertools.groupby('LLLLAAGGG'):
 9     print(char, '-->', list(group))
10 # L --> ['L', 'L', 'L', 'L']
11 # A --> ['A', 'A']
12 # G --> ['G', 'G', 'G']
13 
14 animals = ['duck', 'eagle', 'rat', 'giraffe', 'bear', 'bat', 'dolphin', 'shark', 'lion']
15 animals.sort(key=len)
16 print(animals)
17 # ['rat', 'bat', 'duck', 'bear', 'lion', 'eagle', 'shark', 'giraffe', 'dolphin']
18 
19 for length, group in itertools.groupby(animals, len):
20     print(length, '-->', list(group))
21 # 3 --> ['rat', 'bat']
22 # 4 --> ['duck', 'bear', 'lion']
23 # 5 --> ['eagle', 'shark']
24 # 7 --> ['giraffe', 'dolphin']
25 
26 for length, group in itertools.groupby(reversed(animals), len):
27     print(length, '-->', list(group))
28 # 7 --> ['dolphin', 'giraffe']
29 # 5 --> ['shark', 'eagle']
30 # 4 --> ['lion', 'bear', 'duck']
31 # 3 --> ['bat', 'rat']
groupby函數用法
 1 import itertools
 2 
 3 print(itertools.tee('ABC'))
 4 # (<itertools._tee object at 0x10dd1e8c8>, 
 5 # <itertools._tee object at 0x10dd1e908>)
 6 
 7 g1, g2 = itertools.tee('ABC')
 8 
 9 print(next(g1))
10 # A
11 print(next(g2))
12 # A
13 print(next(g2))
14 # B
15 print(list(g1))
16 # ['B', 'C']
17 print(list(zip(*itertools.tee('ABC'))))
18 # [('A', 'A'), ('B', 'B'), ('C', 'C')]
tee函數的用法

 

yield from

場景:若是生成器函數須要產出另外一個生成器生成的值,傳統的解決方法是使用嵌套的for循環

 1 def chain(*iterables):
 2     for it in iterables:
 3         for i in it:
 4             yield i
 5 
 6 
 7 s = 'ABC'
 8 t = tuple(range(3))
 9 print(list(chain(s, t)))
10 # ['A', 'B', 'C', 0, 1, 2]
傳統寫法
1 def chain_new(*iterables):
2     for i in iterables:
3         yield from i
4 
5 s = 'ABC'
6 t = tuple(range(3))
7 print(list(chain(s, t)))
8 # ['A', 'B', 'C', 0, 1, 2]
yield from的新句法

能夠看出yield from i徹底替代了內層的for循環。在這個示例中使用yield from是對的,並且代碼讀起來更順暢,感受更像是語法糖。除了代替循環以外,yield from還會建立通道,把內層生成器直接與外層生成器的客戶端聯繫起來。把生成器當成協程使用時,這個通道特別重要,不只能爲客戶端生成值,還能使用客戶端代碼提供的值。

 

最值得注意的幾個函數

islice: 容許對一個無窮生成器進行切片

chain: 將多個生成器連接到一塊兒

takewhile: 給生成器添加一個終止條件

cycle: 經過不斷重複將一個有窮生成器變成無窮

相關文章
相關標籤/搜索