摘要:介紹中實(shí)現(xiàn)了很多生成器函數(shù),本篇主要介紹模塊中的生成器。會(huì)過濾掉中所有非元音字母,返回符合元素組成的生成器對(duì)象。函數(shù)等同于下面的生成器表達(dá)式用法。相關(guān)鏈接中的迭代器和生成器
介紹
Python3中實(shí)現(xiàn)了很多生成器函數(shù),本篇主要介紹built-in、itertools、functools模塊中的生成器。
過濾器生成器本類生成器函數(shù)將iterable對(duì)象作為參數(shù),在不改變?cè)搃terable對(duì)象的條件下,返回iterable子集的生成器對(duì)象。
filter(predicate, iterable)iterable的每一個(gè)元素會(huì)傳入predicate函數(shù)中判斷是否為True,該生成器會(huì)返回所有返回為True的元素組成的生成器對(duì)象。
def is_vowel(c): return c.lower() in "aeiou" word = "abcdefghijk" print(list(filter(is_vowel, word))) ## output: ["a", "e", "i"]
filter會(huì)過濾掉word中所有非元音字母,返回符合元素組成的生成器對(duì)象。
注意:通過list(generator)可以將生成器對(duì)象轉(zhuǎn)換為列表,但如果是無(wú)限生成器list將會(huì)產(chǎn)生大量元素導(dǎo)致出錯(cuò)。
filter函數(shù)等同于下面的生成器表達(dá)式用法。
(item for item in iterable if function(item))
如果filter的第一個(gè)參數(shù)為None,則不過濾返回全部,等同于下面的生成器表達(dá)式用法。
(item for item in iterable if item)itertools.filterfalse(predicate, iterable)
該函數(shù)和filter類似,區(qū)別是過濾掉predicate返回True的元素。
print(list(itertools.filterfalse(is_vowel, word))) ## output: ["b", "c", "d", "f", "g", "h", "j", "k"]itertools.takewhile(predicate, iterable)
該函數(shù)連續(xù)迭代iterable對(duì)象中的元素,并用predicate函數(shù)判斷,若predicate返回為True,將不斷產(chǎn)出該元素,直到predicate返回False,過濾了iterable后面不符合的元素。
print(list(itertools.takewhile(is_vowel, word))) ## output: ["a"]itertools.dropwhile(predicate, iterable)
該函數(shù)與itertools.takewhile相反,過濾了iterable對(duì)象前面符合predicate返回True的元素,保留后面的子集。
print(list(itertools.dropwhile(is_vowel, word))) ## output: ["b", "c", "d", "e", "f", "g", "h", "i", "j", "k"]itertools.compress(iterable, selectors)
該函數(shù)中的selectors也是一個(gè)迭代對(duì)象,compress根絕selectors中的值(0/1或是True/False)判斷是否過濾iterable中的元素。
print(list(itertools.compress(word, [1, 0, 1, 0]))) ## output: ["a", "c"]
如果selectors長(zhǎng)度不夠,則iterable后面的對(duì)象全部被過濾掉。
itertools.islice(iterable, stop)根據(jù)傳入?yún)?shù)的個(gè)數(shù)不同,該函數(shù)另一種寫法是itertools.islice(iterable, start, stop[, step]),islice函數(shù)類似python中的分片操作:list[start:stop:step]。
print(list(itertools.islice(word, 4))) ## output: ["a", "b", "c", "d"] print(list(itertools.islice(word, 4, 8))) ## output: ["e", "f", "g", "h"] print(list(itertools.islice(word, 4, 8, 2))) ## output: ["e", "g"]映射生成器
該類生成器主要對(duì)于傳入的一個(gè)或多個(gè)迭代對(duì)象中的每一個(gè)元素進(jìn)行操作,返回映射后的生成器對(duì)象。
map(func, *iterables, timeout=None, chunksize=1)map是Python中常用的原生生成器,將迭代對(duì)象中的每一個(gè)元素傳入func進(jìn)行映射返回新的迭代對(duì)象。如果有n個(gè)iterable對(duì)象,則func的參數(shù)則為n個(gè),后面的timeout和chunksize參數(shù)涉及到異步,本篇將不闡述。
print(list(map(lambda x: x.upper(), word))) print([x.upper() for x in word]) ## output: ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K"]
上面第一行中的map將word中的每個(gè)元素轉(zhuǎn)換為大寫,和第二行中的列表生成式用法相似。
print(list(map(lambda x, y: (x, y), word, word))) print(list(zip(word, word))) ## output: [("a", "a"), ("b", "b"), ("c", "c") ... ("k", "k")]
當(dāng)有兩個(gè)iterable傳入時(shí),func將需要處理傳入的兩個(gè)參數(shù),第一行的用法和zip函數(shù)的作用相似。
itertools.starmap(function, iterable)當(dāng)iterable中的元素也是個(gè)迭代對(duì)象時(shí),如果使用map函數(shù),需要在函數(shù)內(nèi)部實(shí)現(xiàn)解壓操作獲取到單個(gè)元素,而startmap將iterable中的元素按function(*item)方式傳入,我們可以在定義function的參數(shù)時(shí)完成解壓操作。舉例,如果想輸入序列[(2,5), (3,2), (10,3)]來(lái)得到一個(gè)每個(gè)元組元素的和的序列[7, 5, 13], 若使用map方法,fun函數(shù)將會(huì)復(fù)雜,而使用startmap則只需要傳遞一個(gè)add函數(shù)作為startmap參數(shù),元組解壓后的兩個(gè)值將傳入add函數(shù)作為參數(shù)。
from operator import add print(list(map(lambda x: add(x[0], x[1]), [(2, 5), (3, 2), (10, 3)]))) print(list(itertools.starmap(add, [(2, 5), (3, 2), (10, 3)]))) ## output: [7, 5, 13]enumerate(iterable, start=0)
enumerate函數(shù)也是常見的生成器函數(shù),它的主要用法是提供for-in循環(huán)中的索引。若設(shè)置start參數(shù),索引將從start值開始逐1增加。
for i, c in enumerate(word, 2): print(i, c)itertools.accumulate(iterable[, func])
accumulate函數(shù)將通過func函數(shù)完成逐步累加操作,默認(rèn)func為operator.add。下面用例子進(jìn)行說明。
sample = [1, 2, 3, 4, 5] print(list(itertools.accumulate(sample))) ## output: [1, 3, 6, 10, 15] print(list(itertools.accumulate(sample, mul))) ## output: [1, 2, 6, 24, 120] print(list(itertools.accumulate(sample, mul))) ## output: [1, 2, 6, 24, 120] print(list(itertools.accumulate(sample, min))) ## output: [1, 1, 1, 1, 1] print(list(itertools.accumulate(sample, max))) ## output: [1, 2, 3, 4, 5] print(list(itertools.starmap(lambda x, y: y/x, enumerate(itertools.accumulate(sample), 1)))) ## output: [1.0, 1.5, 2.0, 2.5, 3.0]合并生成器
合并生成器接收多個(gè)可迭代對(duì)象參數(shù),將他們組合后返回新的生成器對(duì)象。
itertools.chain(*iterables)chain生成器函數(shù)接收多個(gè)可迭代對(duì)象參數(shù),將他們按順序組合成新的生成器對(duì)象返回。
print(list(itertools.chain(range(3), range(3, 7)))) ## output: [0, 1, 2, 3, 4, 5, 6]itertools.chain.from_iterable(iterable)
chain.from_iterable函數(shù)接收一個(gè)元素為可迭對(duì)象的可迭代對(duì)象,將該所有可迭代的元素拆開,重新按順序組合成一個(gè)新的生成器,新的生成器產(chǎn)出的元素為iterable參數(shù)某個(gè)元素的解壓,chain.from_iterable功能更像是逐層解壓迭代對(duì)象。
a, b = [1,2], [3,4] iterable= [[a,b],[a,b]] print(iterable) new_iterable = list(itertools.chain.from_iterable(iterable)) print(new_iterable) print(list(itertools.chain.from_iterable(new_iterable))) ## output: ## [[[1, 2], [3, 4]], [[1, 2], [3, 4]]] ## [[1, 2], [3, 4], [1, 2], [3, 4]] ## [1, 2, 3, 4, 1, 2, 3, 4]zip(*iterables)
zip函數(shù)接收多個(gè)iterable參數(shù),并提取每個(gè)iterable元素組成元組,返回這些元組組成的生成器對(duì)象。
iterable1 = "abcd" iterable2 = [1, 2, 3] iterable3 = [10, 20, 30, 40] print(list(zip(iterable1, iterable2, iterable3))) ## output: ## [("a", 1, 10), ("b", 2, 20), ("c", 3, 30)]
如果多個(gè)iterable元素個(gè)數(shù)不一致,zip會(huì)在最短的iterable耗盡后停止。
我們可以通過zip函數(shù)生成一個(gè)字典對(duì)象
keys = "abc" values = [1, 2, 3] print(dict(zip(keys, values))) ## output: {"a": 1, "b": 2, "c": 3}itertools.zip_longest(*iterables, fillvalue=None)
zip_longes函數(shù)作用和zip類似,在zip中如果某個(gè)iterable對(duì)象耗盡,生成器將就此停止,而zip_longest函數(shù)將為耗盡的iterable補(bǔ)充fillvalue值。
iterable1 = "abcd" iterable2 = [1, 2, 3] iterable3 = [10, 20, 30, 40] print(list(itertools.zip_longest(iterable1, iterable2, iterable3, fillvalue=0))) ## output: [("a", 1, 10), ("b", 2, 20), ("c", 3, 30), ("d", 0, 40)]itertools.product(*iterables, repeat=1)
product函數(shù)計(jì)算所有iterable的笛卡爾積,它像是生成器表達(dá)式中處理嵌套循環(huán)的步驟,product(a, b)可以等同于((x, y) for x in a for y in b)。
repeat相當(dāng)于擴(kuò)展了iterables, product(a, b, repeat=2)相當(dāng)于product(a, b, a, b)
a = (0, 1) b = (2, 3) print(list(itertools.product(a, b))) print(list(itertools.product(a, repeat=2))) ## output: ## [(0, 2), (0, 3), (1, 2), (1, 3)] ## [(0, 0), (0, 1), (1, 0), (1, 1)]擴(kuò)展生成器
擴(kuò)展生成器將傳進(jìn)的單一對(duì)象進(jìn)行擴(kuò)展,生成更多元素組成的生成器對(duì)象。
itertools.repeat(object[, times])repeat函數(shù)可以接收一個(gè)對(duì)象(可以不是可迭代對(duì)象), 根據(jù)非必選參數(shù)times,生成元素個(gè)數(shù)為times的生成器,如果不提供times參數(shù),將生成無(wú)限生成器。
print(list(itertools.repeat(1, 3))) print(list(itertools.repeat((1, 2), 3))) print(list(zip(range(1, 4), itertools.repeat("a")))) print([1, 2] * 3) """output: [1, 1, 1] [(1, 2), (1, 2), (1, 2)] [(1, "a"), (2, "a"), (3, "a")] [1, 2, 1, 2, 1, 2] """
注意repeat()和列表乘法的區(qū)別,通過上文提到的itertools.chain.from_iterable函數(shù)結(jié)合repeat函數(shù)可以實(shí)現(xiàn)列表乘法。
lst = [1, 2, 3] g = itertools.repeat(lst, 3) print(list(itertools.chain.from_iterable(g))) print(lst * 3) """output [1, 2, 3, 1, 2, 3, 1, 2, 3] [1, 2, 3, 1, 2, 3, 1, 2, 3] """itertools.cycle(iterable)
cycle函數(shù)將傳進(jìn)的iterable可迭代對(duì)象首尾相連形成循環(huán),生成無(wú)限生成器。
# cycle("ABCD") --> A B C D A B C D A B C D ...itertools.count(start=0, step=1)
計(jì)數(shù)器函數(shù),start和step參數(shù)可以為小數(shù),直接看例子。
g = itertools.count(1.2, 2.5) print(next(g)) print(next(g)) print(next(g)) """output: 1.2 3.7 6.2 """
上文提到的enumerate生成器函數(shù)可以通過map和count來(lái)實(shí)現(xiàn)。
for i, v in map(lambda x, y: (x, y), itertools.count(), range(3, 10)): print(i, v)
我們可以通過調(diào)整count函數(shù)讓索引i的值更加靈活。
Python中的range(start, stop[, step])函數(shù)可以生成一個(gè)序列,但是要求輸入?yún)?shù)必須為整數(shù),可以通過count函數(shù)實(shí)現(xiàn)一個(gè)可以接收小數(shù)的新range。
def range_new(start, stop, step): for i in itertools.count(start, step): if i >= stop: break yield i print(list(range_new(1, 5.5, 1.5))) ## output: [1, 2.5, 4.0]排列組合生成器
以下三個(gè)函數(shù)可以實(shí)現(xiàn)迭代對(duì)象的排列組合
itertools.combinations(iterable, r)
非重復(fù)組合
print(list(itertools.combinations("ABC", 1))) print(list(itertools.combinations("ABC", 2))) print(list(itertools.combinations("ABC", 3))) """output: [("A",), ("B",), ("C",)] [("A", "B"), ("A", "C"), ("B", "C")] [("A", "B", "C")] """
itertools.combinations_with_replacement(iterable, r)
重復(fù)組合
print(list(itertools.combinations_with_replacement("ABC", 1))) print(list(itertools.combinations_with_replacement("ABC", 2))) print(list(itertools.combinations_with_replacement("ABC", 3))) """output: [("A",), ("B",), ("C",)] [("A", "A"), ("A", "B"), ("A", "C"), ("B", "B"), ("B", "C"), ("C", "C")] [("A", "A", "A"), ("A", "A", "B"), ("A", "A", "C"), ("A", "B", "B"), ("A", "B", "C"), ("A", "C", "C"), ("B", "B", "B"), ("B", "B", "C"), ("B", "C", "C"), ("C", "C", "C")] """
itertools.permutations(iterable, r=None)
全排列
print(list(itertools.permutations("ABC", 1))) print(list(itertools.permutations("ABC", 2))) print(list(itertools.permutations("ABC", 3))) """output: [("A",), ("B",), ("C",)] [("A", "B"), ("A", "C"), ("B", "A"), ("B", "C"), ("C", "A"), ("C", "B")] [("A", "B", "C"), ("A", "C", "B"), ("B", "A", "C"), ("B", "C", "A"), ("C", "A", "B"), ("C", "B", "A")] """
對(duì)比itertools.product(*iterables, repeat=1)函數(shù)
print(list(itertools.product("ABC", repeat=1))) print(list(itertools.product("ABC", repeat=2))) """output: [("A",), ("B",), ("C",)] [("A", "A"), ("A", "B"), ("A", "C"), ("B", "A"), ("B", "B"), ("B", "C"), ("C", "A"), ("C", "B"), ("C", "C")] """整理生成器
此類生成器將傳入的可迭代對(duì)象經(jīng)過整理后,以生成器的形式全部返回。
itertools.groupby(iterable, key=None)groupby生成器可以根據(jù)key,將iterable分組,返回的生成器的元素為(key, iterable)的元組形式。掃描整個(gè)序列并且查找連續(xù)相同值(或者根據(jù)指定 key 函數(shù)返回值相同)的元素序列。 在每次迭代的時(shí)候,它會(huì)返回一個(gè)值和一個(gè)迭代器對(duì)象, 這個(gè)迭代器對(duì)象可以生成元素值全部等于上面那個(gè)值的組中所有對(duì)象。
g = itertools.groupby("LLLLAAGGG") for char, group in g: print(char, "->", list(group)) """output: L -> ["L", "L", "L", "L"] A -> ["A", "A"] G -> ["G", "G", "G"] """ rows = [ {"address": "5412 N CLARK", "date": "07/01/2012"}, {"address": "5148 N CLARK", "date": "07/04/2012"}, {"address": "5800 E 58TH", "date": "07/02/2012"}, {"address": "2122 N CLARK", "date": "07/03/2012"}, {"address": "5645 N RAVENSWOOD", "date": "07/02/2012"}, {"address": "1060 W ADDISON", "date": "07/02/2012"}, {"address": "4801 N BROADWAY", "date": "07/01/2012"}, {"address": "1039 W GRANVILLE", "date": "07/04/2012"}, ] rows.sort(key=itemgetter("date")) g = itertools.groupby(rows, itemgetter("date")) for char, group in g: print(char, "->", list(group)) """output: 07/01/2012 -> [{"address": "5412 N CLARK", "date": "07/01/2012"}, {"address": "4801 N BROADWAY", "date": "07/01/2012"}] 07/02/2012 -> [{"address": "5800 E 58TH", "date": "07/02/2012"}, {"address": "5645 N RAVENSWOOD", "date": "07/02/2012"}, {"address": "1060 W ADDISON", "date": "07/02/2012"}] 07/03/2012 -> [{"address": "2122 N CLARK", "date": "07/03/2012"}] 07/04/2012 -> [{"address": "5148 N CLARK", "date": "07/04/2012"}, {"address": "1039 W GRANVILLE", "date": "07/04/2012"}] """
groupby() 僅僅檢查連續(xù)的元素,因此在調(diào)用之前需要根據(jù)指定的字段將數(shù)據(jù)排序。
reversed(seq)reversed函數(shù)接收一個(gè)序列(實(shí)現(xiàn)sequence相關(guān)協(xié)議,已知長(zhǎng)度)
print(list(reversed(range(5)))) ## output: [4, 3, 2, 1, 0]itertools.tee(iterable, n=2)
tee函數(shù)返回單個(gè)iterable對(duì)象的n個(gè)獨(dú)立迭代器
g1, g2 = itertools.tee("ABC") print(next(g1), next(g2)) print(next(g1), next(g2)) print(list(zip(*itertools.tee("ABC")))) """output A A B B [("A", "A"), ("B", "B"), ("C", "C")] """縮減生成器
接收一個(gè)迭代對(duì)象,處理只返回一個(gè)單一值。
functools.reduce(function, iterable,initializer=None)function參數(shù)是一個(gè)接收兩個(gè)參數(shù)的函數(shù)function(x, y),reduce函數(shù)將上一次function得到的返回值作為參數(shù)x,將iterable的下一次迭代值作為參數(shù)y傳進(jìn)function計(jì)算,初始時(shí)x的值為initializer值(若initializer為None,初始值則為iterable的第一個(gè)元素值)。循環(huán)直到iterable耗盡返回最終值。
reduce的基本實(shí)現(xiàn)大概為一下代碼:
def reduce(function, iterable, initializer=None): it = iter(iterable) if initializer is None: value = next(it) else: value = initializer for element in it: value = function(value, element) return value
print(functools.reduce(add, [1, 2, 3, 4, 5])) ## output: 15
常用的min和max函數(shù)都可以用reduce實(shí)現(xiàn)
def min_reduce(iterable): return functools.reduce(lambda x, y: x if x < y else y, iterable) def max_reduce(iterable): return functools.reduce(lambda x, y: x if x > y else y, iterable) print(min_reduce([4, 6, 6, 78])) print(max_reduce([4, 6, 6, 78])) """output 4 78 """
除此之外any和all函數(shù)原理也是類似,不再闡述。
總結(jié)本篇按照分類介紹了python庫(kù)中的一些常用的生成器,可以通過不同場(chǎng)景選擇不同的生成器工具,將它們組合靈活運(yùn)用。
相關(guān)鏈接Python3中的迭代器和生成器
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/42621.html
摘要:常規(guī)的使用來(lái)統(tǒng)計(jì)一段代碼運(yùn)行時(shí)間的例子輸出結(jié)果總結(jié)其實(shí)是一門特別人性化的語(yǔ)言,但凡在工程中經(jīng)常遇到的問題,處理起來(lái)比較棘手的模式基本都有對(duì)應(yīng)的比較優(yōu)雅的解決方案。 python的高級(jí)特性 名詞與翻譯對(duì)照表 generator 生成器 iterator 迭代器 collection 集合 pack/unpack 打包/解包 decorator 裝飾器 context manager ...
摘要:比較的是兩個(gè)對(duì)象的內(nèi)容是并發(fā)編程之協(xié)程異步后端掘金引言隨著的盛行,相信大家今年多多少少都聽到了異步編程這個(gè)概念。使用進(jìn)行并發(fā)編程篇二掘金我們今天繼續(xù)深入學(xué)習(xí)。 python 之機(jī)器學(xué)習(xí)庫(kù) scikit-learn - 后端 - 掘金一、 加載sklearn中的數(shù)據(jù)集datasets from sklearn import datasets iris = datasets.load_i...
摘要:將每一行作為返回,其中是每行中的列名。對(duì)于每一行,都會(huì)生成一個(gè)對(duì)象,其中包含和列中的值。它返回一個(gè)迭代器,是迭代結(jié)果都為的情況。深度解析至此全劇終。 簡(jiǎn)單實(shí)戰(zhàn) 大家好,我又來(lái)了,在經(jīng)過之前兩篇文章的介紹后相信大家對(duì)itertools的一些常見的好用的方法有了一個(gè)大致的了解,我自己在學(xué)完之后仿照別人的例子進(jìn)行了真實(shí)場(chǎng)景下的模擬練習(xí),今天和大家一起分享,有很多部分還可以優(yōu)化,希望有更好主意...
閱讀 3580·2021-08-02 13:41
閱讀 2472·2019-08-30 15:56
閱讀 1530·2019-08-30 11:17
閱讀 1190·2019-08-29 15:18
閱讀 592·2019-08-29 11:10
閱讀 2684·2019-08-26 13:52
閱讀 521·2019-08-26 13:22
閱讀 2965·2019-08-23 15:41