生成器(Generator)是一种特殊的迭代器,它允许你在迭代过程中动态生成值,而不是一次性生成所有值并存储在内存中。
和元组等迭代器相比,元组之类是在打一开始就将可迭代对象都写好了,调用时一个个给出,都是既定存在的对象。而生成器,顾名思义是调用时先生成,才有这些对象给出。
创建方式
- 生成器函数
将普通函数里的return替换成yield关键字的函数,就叫生成器函数。def fibonacci(): a, b = 0, 1 #初始化变量a,b while True: #无限循环 yield a #执行到yield所在行时,函数便会暂停,a的当前值即作为生成器的返回值 #再下一次调用时,函数会从yield下一行开始继续运行,直到再次遇到yield语句或函数结束 a, b = b, a + b # 生成前 5 个斐波那契数 fib_gen = fibonacci() for _ in range(5): print(next(fib_gen)) >>>0 1 1 2 3
- 生成器表达式
利用推导的形式获得生成器。gen = (x for x in range(2)) print(next(gen)) # 输出: 0 print(next(gen)) # 输出: 1
与普通可迭代对象相较的特点
- 延迟计算
- 生成器只在需要时才生成下一个值,而不是一次性生成所有值,所谓“惰性生成”。好处就是在处理大量数据或需要复杂计算的场景非常有用,可以节省内存。例如,生成一个包含 1 到 1000000 的平方的列表会占用大量内存,但使用生成器可以在需要时逐个生成这些值。
- 普通可迭代对象则会一次性将所有元素存储在内存中。如果元组包含大量元素,会占用较多的内存空间。
- 只能遍历一次
- 生成器是一次性的,一旦遍历完所有元素,再次遍历将不会有任何输出。这是因为生成器在遍历过程中会记住当前的状态,当所有元素都被遍历完后,它就耗尽了。也因此,生成器自然是无法多次访问,也无法使用下标索引来进行随机访问的。
- 普通可迭代对象则可以被多次遍历,每次遍历都会从头开始,也可以通过指定下表索引的方式来进行访问,因为例如元组的元素是固定存储在内存中的。
- 支持 next() 函数
- 生成器可以使用 next() 函数手动获取生成器的下一个值。当生成器耗尽时,调用 next() 函数会抛出 StopIteration 异常。
- 普通可迭代对象本身则不支持,需要用iter()函数将其转换为迭代器后才能直接使用。