前言
标准库提供了很多生成器,有些是内置的,有些在itertools和functools模块中,下面我们就按照它们的功能进行分组来看看它们吧!
用于过滤的生成器函数
import itertools
# itertools.compress(it,selector_it)
# 并行处理两个可迭代对象,如果selector_it中的元素是真值,产出it中对应的元素
print([i for i in itertools.compress(range(10), [0, 0, 1, 1])])
# itertools.takewhile(predicate,it)
# 使用传入的生成器生成另一个生成器,predicate指定终止条件
print([i for i in itertools.takewhile(lambda n: n < 5, range(10))])
# itertools.dropwhile(prdicate,it)
# 与itertools.takewhile的作用相反
print([i for i in itertools.dropwhile(lambda n: n < 5, range(10))])
# filter(predicate,it)
# 将it中的各个元素传给predicate,如果为真,则产出it中对应的元素
print([i for i in filter(lambda a: a % 2, range(10))]) # 保留奇数
# itertools.filterfalse(predicate,it)
# 与filter的作用相反
print([i for i in itertools.filterfalse(lambda a: a % 2, range(10))]) # 保留偶数
# itertools.islice(it,stop)或者itertools.islice(it,start,stop,step=1)
# 产出it的切片 实现的是惰性操作
print([i for i in itertools.islice(range(10), 2)])
print([i for i in itertools.islice(range(10), 2, 9, 3)])
#end
用于映射的生成器函数
import itertools
import fractions
import operator
# itertools.accumulate(it,func)
# 产出累积的总和,如果提供了func,那么把前两个元素传给它,然后把计算的结果和下一个元素传给它,以此类推
print([i for i in itertools.accumulate(range(10), lambda a, b: a + b)]) # 计算前n项的和
# enunerate(it,start=0)
# 产出由两个元素构成的元组 结构是(index,item) index从start开始,每次加一 item的值中it中取
print([i for i in enumerate(range(10), start=10)])
# map(func,iter,[it2,...itn])
# 把it中的各个元素传给func,产出结果,如果传入n个it,func的参数必须有n个
print([i for i in map(lambda a, b, c: a + b + c, range(-10, 0, 1), range(10), range(10, 20))]) # 对it1,it2,it3对应位置的元素进行求和
# itertools.startmap(func,it)
# 把it中的各个元素传给func,产出结果
print([i for i in itertools.starmap(operator.mul, enumerate('hello world', 1))]) # 从1开始,根据字母所在位置,把字母重复相应的次数
合并多个可迭代对象的生成器函数
import itertools
# itertools.chain(it1,[it2...it2])
# 先产出it1中的元素,然后产出it2中的元素,以此类推,无缝连接在一起
print([i for i in itertools.chain(range(10), range(11, 20), 'hello world')])
# itertools.chain.from_iterable(it)
# 功能同itertools.chain 不过传入的参数的结构有所变化 it的结构:it=[iter1,[iter2...itern]]
print([i for i in itertools.chain.from_iterable([range(10), 'hello'])])
# itertools.product(it1,...itn,repeat=1)
# 计算笛卡尔积,从输入的各个可迭代对象中获取元素,合并成由N个元素组成的元组,与嵌套的for循环效果一样,repeat指明重复处理多少次输入的可迭代对象
print([i for i in itertools.product(range(3), 'hello', 'world', repeat=1)])
# zip(it1,...itn)
# 并行从输入的各个可迭代对象中获取元素,产出由N个元素组成的元组,只要有一个可迭代对象到了头,迭代就终止
print([i for i in zip(range(5), 'hello')])
# zip_longest(it1,..itn,fillvalue=None)
# 与zip作用一样,但是终止条件是最长的可迭代对象到头了才终止,其他可迭代对象空缺的值用fillvalue进行补充
print([i for i in itertools.zip_longest(range(10), 'hello', fillvalue='world')])
把输入的各个元素扩展成多个输出元素的生成器函数
import itertools
# itertools.combinations(it,out_len) 组合 和顺序无关
# 把it产出的out_len个元素组合在一起,然后产出
print([i for i in itertools.combinations('ABC', 2)]) # 产出两两组合的元素
# itertools.combinations_with_replacement 组合
# 功能同itertools.combinations,但是也包含自己和自己的组合
print([i for i in itertools.combinations_with_replacement('ABC', 2)])
# itertools.count(start=0,step=1)
# 从start开始,以step为步长,不断产出数字
for i in itertools.count(1, 2):
print(i, end=' ')
if i > 10: break
print()
# itertools.permutations(it,out_len=len(list(it)))
# 把it产出的out_len个元素排列在一起 排列 和顺序有关
print([i for i in itertools.permutations('ABC', 2)])
# repeat(item,[times])
# 重复不断的产出指定的元素,除非提供times指定次数
print([i for i in itertools.repeat('hello', 10)])
# itertools.cycle(it)
# 从it中产出各个元素,存储各个元素的副本,然后按顺序重复不断地产出各个元素
cy = itertools.cycle('ABC') # 将it首位相连
while True:
print(next(cy))
break
用于重新排列元素的生成器函数
import itertools
# itertools.groupby(it,key=None)
# 产出由练个元素组成的元素,形式为(key,group),其中key是分组标准,group是生成器,用于产出分组里的元素
strs_list = ['hello', 'world', 'we', 'price', 'the', 'things', 'when', 'we', 'have', 'lost', 'them', '.']
strs_list.sort(key=len) # 先排序
for key, group in itertools.groupby(strs_list, key=len): # 根据元素的长度进行分组
print(key, list(group))
# reversed(seq)
# 从后向前,倒序产出seq seq必须是序列,或者是实现了__reversed__的对象
print(list(reversed(strs_list)))
# itertools.tee(it,n=2)
# 产出一个由n个生成器组成的元组,每个生成器用于单独产出输入的可迭代对象中的元素
g1, g2 = itertools.tee('ABC')
print(list(g1))
print(list(g2))
总结
python的大部分的内置功能都是用c实现的,这些生成器函数也不例外,它们不仅功能强大,性能也是相当不错的,因此,掌握它们对你的代码优化上会有不小的帮助哦!
同步更新于个人博客系统:python标准库中的24个生成器函数,个个都超级厉害,你用过几个?