标准库中的生成器函数
这里主要记录流畅的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',)]
浙公网安备 33010602011771号