生成器是构造新的可遍历对象的一种简洁的方式,普通的函数,在执行一次之后并返回单个结果,而生成器会返回一个多结果序列,在每一个元素产生之后暂停,知道下一个请求。
创建生成器只需要把关键词换成yield关键字:
def squares(n=10):
print('Generating squares from 1 to {0}'.format(n ** 2))
for i in range(1, n+1):
yield i ** 2
gen = squares()
print(gen)
#打印
<generator object squares at 0x7fb6688639a8>
#使用for循环调用:
for x in gen:
print(x)
#打印
Generating squares from 1 to 100
1 4 9 16 25 36 49 64 81 100
这样简单的函数,还可以通过表达式来表示:
#接上面代码
gen = (x ** x for x in range(100)) #这里是另一种for表达方式
print(gen)
#打印
<generator object squares at 0x7fb6688639a8>
生成是可以当做参数传递给内建的函数的,max、min、sum、dict等等:
gen = (x**2 for x in range(100))
print(sum(gen))
#打印
328350
gen = (i, i**2) for i in range(5)
print(dict(gen))
#打印
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
itertools 模块,这是数据算法的生成器集合,常用的到如下:
combinations(iterable, k) #根据iterable参数中的所有元素生成一个包含所有可能k元组的序列,忽略元素的顺序,不进行替代
combinations_replacement(iterable, k) #同上,只是会替代
permutations(iterable, k) #根据iterable参数中的所有元素按顺序生成包含所有可能k元组的序列
groupby(iterable[, keyfunc]) #根据每一个独一的key生成(key, sub-iterator)元组
product(*iterables, repeat=1) #以元组的形式,根据输入的可遍历对象生成笛卡尔积,与嵌套的for循环类似
下面是一个groupby的示例,根据首字母将字符串数组分组:
first_charater = lambda x : x[0]
arr_names = ['Zhou', 'Zhang', 'Lin', 'Liu', 'Guang', 'Guo', 'Xiao', 'Xian']
# arr_names.sort(key=first_charater)
# print(arr_names)
for c, n in itertools.groupby(arr_names, first_charater):
print(c, list(n))
#打印
Z ['Zhou', 'Zhang']
L ['Lin', 'Liu']
G ['Guang', 'Guo']
X ['Xiao', 'Xian']
#注意,如果数组里面没有排序,groupby之后,不会完全分组好,我们需要做进一步处理,比如,先排序,然后在分组