标准库中的生成器函数
这里主要记录流畅的Python书中P349页介绍关于内置itertoos模块中的内置生成器。(19个)
第一组是用于过滤的生成器函数:从输入的可迭代对象中产出元素的子集,而且不修改元素本身。
compress(it, selector_it)
In [133]: compress? Init signature: compress(self, /, *args, **kwargs) Docstring: compress(data, selectors) --> iterator over selected data Return data elements corresponding to true selector elements. Forms a shorter iterator from selected data elements using the selectors to choose the data elements. Type: type Subclasses:
并行处理两个可迭代对象;如果selector_it中的元素是真值,产出it中对应的元素。
In [134]: com = compress('123456789',[1,0,1,False,'',True]) In [135]: com Out[135]: <itertools.compress at 0x1105c8e10> In [136]: list(com) Out[136]: ['1', '3', '6'] In [137]:
dropwhile与takewhile
dropwhile(predicate, it):
处理it,跳过predicate的计算为真的值,然后产出剩下的各个元素(剩下的元素不在检查)
takewhile(predicate, it):
处理it,predicate返回为真值的产出对应元素,遇到返回为假,立即停止,不在继续检查(剩下的元素不在检查)
两个蛮有意思的返回生成器的类,第一个,返回是真的都跳过,遇到一个假的,后面的都要.(取后面)
第二个,遇到真的都要,遇到假的后面都不要。(取前面)
In [137]: drop = dropwhile(lambda x:x<3,range(5)) In [138]: list(drop) Out[138]: [3, 4] In [139]: type(dropwhile) Out[139]: type In [140]: drop = dropwhile(lambda x:x != 'a','cccaddd') In [141]: list(drop) Out[141]: ['a', 'd', 'd', 'd'] In [142]:
In [142]: take = takewhile(lambda x:x <5,count(1,3)) In [143]: list(take) Out[143]: [1, 4] In [144]:
filter与filterfalse(遍历全部元素)
filter(predicate, it):逐个遍历it中的所有元素,放入predicate,返回predicate返回是真的值的元素。
filterflase(predicate, it):逐个遍历it中的所有元素,放入predicate,返回predicate返回是假的值的元素。
In [144]: vowel = lambda x: x.lower() in 'aeiou' In [145]: list(filter(vowel,'Aardvark')) Out[145]: ['A', 'a', 'a'] In [146]: list(filterfalse(vowel,'Aardvark')) Out[146]: ['r', 'd', 'v', 'r', 'k'] In [147]:
islice(it, stop)或islice(it, start,stop,step=1)
产出it的切片,作用类似于s[:stop]或s[start:stop:strp],不过it可以是任何可迭代对象,而且这个类实现是惰性操作。
实际操作跟这个功能一样iter(it[:stop])或iter(it[start:stop:step=1])
In [160]: list(islice('Aardvark',4)) Out[160]: ['A', 'a', 'r', 'd'] In [161]: list(islice('Aardvark',4,7)) Out[161]: ['v', 'a', 'r'] In [162]: list(islice('Aardvark',4,7,2)) Out[162]: ['v', 'r'] In [163]: list(iter('Aardvark'[4:7:2])) Out[163]: ['v', 'r'] In [164]:
用于映射的生成器类。(扫描全部元素)
accmulate(it,[func])
产出累积的总和,如果提供了func,那么把前两个元素传给它,然后把计算结果和下一个元素传给它,以此类推,最后产出结果。
n [167]: import random In [168]: sample = list(range(10)) In [169]: random.shuffle(sample) In [170]: sample Out[170]: [5, 2, 3, 1, 4, 0, 6, 9, 7, 8] In [171]: list(accumulate(sample)) Out[171]: [5, 7, 10, 11, 15, 15, 21, 30, 37, 45] In [173]: list(accumulate(sample,max)) Out[173]: [5, 5, 5, 5, 5, 5, 6, 9, 9, 9] In [174]: list(accumulate(sample,min)) Out[174]: [5, 2, 2, 1, 1, 0, 0, 0, 0, 0] In [175]: from operator import mul In [176]: list(accumulate(sample,mul)) Out[176]: [5, 10, 30, 30, 120, 0, 0, 0, 0, 0] In [177]:
emumetate(iterable, start=0)(内置)
产出两个元素组成的元祖,结构是(index,item),其中index从start开始计算,item则从iterable中获取
In [177]: list(enumerate('hello')) Out[177]: [(0, 'h'), (1, 'e'), (2, 'l'), (3, 'l'), (4, 'o')] In [178]: list(enumerate(range(1,10),start=1)) Out[178]: [(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6), (7, 7), (8, 8), (9, 9)] In [179]:
map(func,it1,[it2,...itN])(内置)
把it中的各个元素传给func,产出结果,如果传入N个可迭代对象,那么func必须能接收N个参数,而且也要并行处理各个可迭代对象。
In [179]: list(map(mul,range(11),range(11))) Out[179]: [0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100] In [180]: list(map(mul,range(11),(1,2,3))) Out[180]: [0, 2, 6] In [181]: list(map(lambda a,b:(a,b),range(11),(1,2,3))) Out[181]: [(0, 1), (1, 2), (2, 3)] In [182]:
starmap(func, it)
把it中的各个元素传给func,产出结果;输入的可迭代对象产出可迭代的元素iit,然后以func(*iit)这种形式调用func
讲的很抽象,或者翻译的很差,其实简单来说,it里买的元素必须是可解包的元素,每次返回的是解包后的参数,传递给func返回的值。
In [182]: list(starmap(mul,enumerate('albatroz',1))) Out[182]: ['a', 'll', 'bbb', 'aaaa', 'ttttt', 'rrrrrr', 'ooooooo', 'zzzzzzzz'] In [183]: sample Out[183]: [5, 2, 3, 1, 4, 0, 6, 9, 7, 8] In [184]: list(starmap(lambda a,b:b/a,enumerate(sample,1))) Out[184]: [5.0, 1.0, 1.0, 0.25, 0.8, 0.0, 0.8571428571428571, 1.125, 0.7777777777777778, 0.8] In [185]:
我搞个简单的看看,就比较直接。
In [186]: list(starmap(add,((1,2),(3,4)))) Out[186]: [3, 7] In [187]:
In [187]: a = 1,2,3 In [188]: b = 2,3,4 In [189]: lz = zip(a,b) In [190]: list(starmap(add,lz)) Out[190]: [3, 5, 7] In [191]:
合并多个可迭代对象的生成器类
chain(it1,...,itN)
先产出it1中的所有元素,然后产出it2中的所有元素,以此类推,无缝连接在一起
In [200]: list(chain.from_iterable(('12345',[1],('c')))) Out[200]: ['1', '2', '3', '4', '5', 1, 'c'] In [201]: list(chain('abc,',range(10))) Out[201]: ['a', 'b', 'c', ',', 0, 1, 2, 3, 4, 5, 6, 7, 8, 9] In [202]: list(chain(enumerate('hello'))) Out[202]: [(0, 'h'), (1, 'e'), (2, 'l'), (3, 'l'), (4, 'o')] In [203]: list(chain.from_iterable(enumerate('hello'))) Out[203]: [0, 'h', 1, 'e', 2, 'l', 3, 'l', 4, 'o'] In [204]:
chain.from_iterable(it)
从it这个可迭代对象中取出元素,每个元素为可迭代对象,然后把所有的it中的所有元素无缝连接在一起。
上面已经示例了。
zip(it1.....,itN)(内置)
并行从输入的各个可迭代对象中获取元素,产出由N个元素组成的元祖,只要有一个可迭代的对象到头了,就停止。
zip_longest(it1,....,itN, fillvalue=None)
并行从输入的各个可迭代对象中获取元素,产出由N个元素组成的元祖,等到最长的可迭代对象到头才停止,空缺的值使用fillvalue填充。
In [206]: list(zip('abc',range(10))) Out[206]: [('a', 0), ('b', 1), ('c', 2)] In [207]: list(zip('abc',range(100),[3,4,5,6])) Out[207]: [('a', 0, 3), ('b', 1, 4), ('c', 2, 5)] In [208]: list(zip_longest('abc',range(8),[1,2],fillvalue='?')) Out[208]: [('a', 0, 1), ('b', 1, 2), ('c', 2, '?'), ('?', 3, '?'), ('?', 4, '?'), ('?', 5, '?'), ('?', 6, '?'), ('?', 7, '?')] In [209]:
product(it1,...itN, repeat=1)
计算迪凯尔积:从输入的各个可迭代对象中获取元素,合并成有N个元素组成的元祖,与嵌套的for循环效果一样;repeat指明重复处理多少次输入的可迭代对象。
普通两个可迭代对象,就像双层的for循环返回的元祖组合。
In [209]: list(product('ABC','ABc')) Out[209]: [('A', 'A'), ('A', 'B'), ('A', 'c'), ('B', 'A'), ('B', 'B'), ('B', 'c'), ('C', 'A'), ('C', 'B'), ('C', 'c')] In [210]: list(product('abc',range(2))) Out[210]: [('a', 0), ('a', 1), ('b', 0), ('b', 1), ('c', 0), ('c', 1)] In [211]: suits = 'spades hearts diamonds clubs'.split() In [212]: list(product('AK',suits)) Out[212]: [('A', 'spades'), ('A', 'hearts'), ('A', 'diamonds'), ('A', 'clubs'), ('K', 'spades'), ('K', 'hearts'), ('K', 'diamonds'), ('K', 'clubs')] In [213]: list(product('ABC')) Out[213]: [('A',), ('B',), ('C',)] In [214]: list(product('ABC',repeat=2)) Out[214]: [('A', 'A'), ('A', 'B'), ('A', 'C'), ('B', 'A'), ('B', 'B'), ('B', 'C'), ('C', 'A'), ('C', 'B'), ('C', 'C')] In [215]: list(product('ABC','ABC')) Out[215]: [('A', 'A'), ('A', 'B'), ('A', 'C'), ('B', 'A'), ('B', 'B'), ('B', 'C'), ('C', 'A'), ('C', 'B'), ('C', 'C')] In [216]: list(product('AB',range(2),repeat=2)) Out[216]: [('A', 0, 'A', 0), ('A', 0, 'A', 1), ('A', 0, 'B', 0), ('A', 0, 'B', 1), ('A', 1, 'A', 0), ('A', 1, 'A', 1), ('A', 1, 'B', 0), ('A', 1, 'B', 1), ('B', 0, 'A', 0), ('B', 0, 'A', 1), ('B', 0, 'B', 0), ('B', 0, 'B', 1), ('B', 1, 'A', 0), ('B', 1, 'A', 1), ('B', 1, 'B', 0), ('B', 1, 'B', 1)] In [217]: list(product('AB',range(2),'AB',range(2))) Out[217]: [('A', 0, 'A', 0), ('A', 0, 'A', 1), ('A', 0, 'B', 0), ('A', 0, 'B', 1), ('A', 1, 'A', 0), ('A', 1, 'A', 1), ('A', 1, 'B', 0), ('A', 1, 'B', 1), ('B', 0, 'A', 0), ('B', 0, 'A', 1), ('B', 0, 'B', 0), ('B', 0, 'B', 1), ('B', 1, 'A', 0), ('B', 1, 'A', 1), ('B', 1, 'B', 0), ('B', 1, 'B', 1)] In [218]:
product返回的都是元祖的组合,product里面有几个可迭代元素,就代码这个生成的元素内元祖的元素数量,repert默认为1,设置不同的repert可以看出就是重复带入一遍前面的可迭代元素。
把输入的各个元素扩展成多个输出的生成器函数。(要么接收一个可迭代对象),count与repert不用接收可迭代对象作为输入
combinations(it, out_len)
把it产出的out_len个元素组合在一起,然后产出。
combinations_with_replacement(it, outlen)
把it产出的out_len个元素组合在一起,然后产出,包含相同元素的组合。
In [218]: list(combinations('abc',2)) Out[218]: [('a', 'b'), ('a', 'c'), ('b', 'c')] In [219]: list(combinations_with_replacement('abc',2)) Out[219]: [('a', 'a'), ('a', 'b'), ('a', 'c'), ('b', 'b'), ('b', 'c'), ('c', 'c')]
permutations(it, out_len=None)
把it产出的out_len个元素排列在一起,然后产出。
In [220]: list(permutations('abc',2)) Out[220]: [('a', 'b'), ('a', 'c'), ('b', 'a'), ('b', 'c'), ('c', 'a'), ('c', 'b')] In [221]: list(product('abc',repeat=2)) Out[221]: [('a', 'a'), ('a', 'b'), ('a', 'c'), ('b', 'a'), ('b', 'b'), ('b', 'c'), ('c', 'a'), ('c', 'b'), ('c', 'c')] In [222]:
cycle(it)
从it中产出各个元素,存储各个元素的副本,然后按顺序重复不断地产出各个元素。
In [236]: c = cycle('ok') In [237]: next(c) Out[237]: 'o' In [238]: In [238]: next(c) Out[238]: 'k' In [239]: next(c) Out[239]: 'o' In [240]: next(c) Out[240]: 'k' In [241]:
count(start=0,step=1) 不需要接收可迭代元素作为参数
从start开始不断产出数字,按step指定的步幅增加
In [225]: c = count() In [226]: next(c) Out[226]: 0 In [227]: next(c) Out[227]: 1 In [228]: next(c) Out[228]: 2 In [229]: c = count(3,0.1) In [230]: next(c) Out[230]: 3 In [231]: next(c) Out[231]: 3.1 In [232]: next(c) Out[232]: 3.2 In [233]: next(c) Out[233]: 3.3000000000000003 In [234]: next(c) Out[234]: 3.4000000000000004 In [235]: next(c) Out[235]: 3.5000000000000004
repert(item,[times]) 不需要接收可迭代元素作为参数
重复不断产出指定的元素,除非提供times指定次数。
In [241]: r = repeat(3,2) In [242]: next(r) Out[242]: 3 In [243]: next(r) Out[243]: 3 In [244]: next(r) --------------------------------------------------------------------------- StopIteration Traceback (most recent call last) <ipython-input-244-8ebe59a56b1d> in <module> ----> 1 next(r) StopIteration: In [245]: list(map(mul, range(10),repeat(5,3))) Out[245]: [0, 5, 10] In [246]:
用于重新排列元素的生成器函数。
groupby(it,key=None) (先排好序)
产出由两个元素组成的元素,形式为(key,group),其中key是分组标准,group是生成器,用于产出分组里的元素。
默认的分组标准是相同的元素为一组,用==判断。
In [259]: s = ('123123123123') In [260]: list(groupby(s)) Out[260]: [('1', <itertools._grouper at 0x10fd00250>), ('2', <itertools._grouper at 0x11050d550>), ('3', <itertools._grouper at 0x11050d8d0>), ('1', <itertools._grouper at 0x11050d4d0>), ('2', <itertools._grouper at 0x1101e9f90>), ('3', <itertools._grouper at 0x1101e92d0>), ('1', <itertools._grouper at 0x1101e9610>), ('2', <itertools._grouper at 0x1102ec6d0>), ('3', <itertools._grouper at 0x1105c3dd0>), ('1', <itertools._grouper at 0x1105c3fd0>), ('2', <itertools._grouper at 0x1105c3b50>), ('3', <itertools._grouper at 0x1105c3e10>)] In [261]: s = sorted(s) In [262]: s Out[262]: ['1', '1', '1', '1', '2', '2', '2', '2', '3', '3', '3', '3'] In [263]: list(groupby(s)) Out[263]: [('1', <itertools._grouper at 0x10f8f21d0>), ('2', <itertools._grouper at 0x10f8f2090>), ('3', <itertools._grouper at 0x10f6dce50>)]
In [266]: for char, group in groupby(s): ...: print(char,'->',list(group)) ...: 1 -> ['1', '1', '1', '1'] 2 -> ['2', '2', '2', '2'] 3 -> ['3', '3', '3', '3']
In [267]: animails = ['duck','eagle','rat','giraffe','bear','bat'] In [268]: animails.sort(key=len) In [269]: animails Out[269]: ['rat', 'bat', 'duck', 'bear', 'eagle', 'giraffe']
In [271]: for length,group in groupby(animails,key=len): ...: print(length,'->',list(group)) ...: ...: 3 -> ['rat', 'bat'] 4 -> ['duck', 'bear'] 5 -> ['eagle'] 7 -> ['giraffe'] In [272]: for length,group in groupby(reversed(animails),key=len): ...: print(length,'->',list(group)) ...: ...: ...: 7 -> ['giraffe'] 5 -> ['eagle'] 4 -> ['bear', 'duck'] 3 -> ['bat', 'rat']
reversed(seq)内置
所有iteritools里面唯一一个不接受可迭代的对象,而只接受序列为参数的函数。
从后向前,倒序产出seq中的元素;seq必须是序列,或者是实现了__reversed__特殊方法的对象。
tee(it, n=2) 返回的是元祖,应该是唯一一个工具里面返回是元祖的。
产生一个由n个生成器组成的元祖,每个生成器用于单独产出输入的可迭代对象中的元素。
分神器,可以一个可迭代对象,产生多个该可迭代对象的生成器。
In [273]: s = tee('abc') In [274]: s Out[274]: (<itertools._tee at 0x10fd67eb0>, <itertools._tee at 0x10c19daf0>) In [275]: type(s) Out[275]: tuple In [276]: a,b=s In [277]: next(a) Out[277]: 'a' In [278]: next(a) Out[278]: 'b' In [279]: next(a) Out[279]: 'c' In [280]: list(b) Out[280]: ['a', 'b', 'c'] In [281]: list(zip(tee('abc'))) Out[281]: [(<itertools._tee at 0x10fb79eb0>,), (<itertools._tee at 0x10d49c1e0>,)] In [282]: list(zip(*tee('abc'))) Out[282]: [('a', 'a'), ('b', 'b'), ('c', 'c')] In [283]:
刚发现,zip一个蛮好用的功能,能把一个可迭代元素,每个元素拆分成一个个独立的元祖:
In [283]: list(zip('hello')) Out[283]: [('h',), ('e',), ('l',), ('l',), ('o',)]