生成器 / Generator
目录
1 关于生成器
从计算机科学角度上看,生成器是一种类协程或半协程(Semi-coroutine),生成器提供了一种可以通过特定语句或方法来使生成器的执行对象(Execution)暂停,而这语句一般都是 yield。通过 yield 语句将每一次的结果切出执行对象,并带到主线程上来。yield 可以将一个值带出协程,而主线程也可以通过生成器对象的方法将一个值带回生成器的执行对象中去。
在 Python 中生成器常是一个由生成器函数产生的对象,可以使用 nex t函数调用其内部参数,直到所有参数均被生成返回耗尽,则返回一个 StopIteration 异常。在生成器中,返回参数值使用的不是 return 而是 yield,也正是这个 yield 使其所在的函数变成了一个生成器。
对于生成器来说,它不会把结果保存在特定序列中,而是将生成器的状态进行保存。每一次 yield 后都会保存生成器的上下文(包括内部状态及变量值),当下次迭代到来时,则从 yield 处继续生成器的后续函数,且内部状态均为上次 yield 前的状态。
2 生成器与迭代器
而对于生成器与迭代器的关系,可以说每一个生成器都是一个迭代器,反之不亦然。也可以认为,生成器是一个带有迭代器特性,并且具有一个或多个 yield 表达式的对象。
通过源码可以查看到,generator 的基类为 iterator。
3 生成器的建立
生成器的建立主要有以下两种:
1. 通过函数中的 yield 表达式,挂起函数;
2. 对于可迭代对象,使用[]推导时会遍历可迭代对象产生一个列表,而使用()推导时,会返回可迭代的对象作为一个生成器。
关于生成器的生成,可以使用以下两种方式,即分别使用()推导和 yield 进行生成
1 # Use () to replace [], make it into a generator 2 gen = (x**2 for x in range(7)) 3 lis = [x**2 for x in range(7)] 4 print(type(gen), type(lis)) 5 6 # Define function to create generator by using yield 7 # Return will cause StopIertation and return value will be present as an explaination for StopIteration 8 def gener(m): 9 n = 1 10 while n < m: 11 yield n 12 n += 1 13 if n == 3: 14 return 'Stop at 3' 15 16 # gener is function, while gener(7) is generator 17 print(type(gener), type(gener(7)))
输出结果为
<class 'generator'> <class 'list'> <class 'function'> <class 'generator'>
通过输出的第一行结果可以看到,通过[]推导得到的是一个 list ,而通过 ()推导得到的是一个生成器类,即返回的是生成器对象。
而对于 yield 方式生成的生成器,可以看到,生成生成器的 gener 是一个函数,而调用函数之后返回的结果 gener(m) 则是一个生成器。
同时,还可以通过 help 查看生成器内部的一些信息,
1 help(gener(10))
输出结果
Help on generator object: gener = class generator(object) | Methods defined here: | | __del__(...) | | __getattribute__(self, name, /) | Return getattr(self, name). | | __iter__(self, /) | Implement iter(self). | | __next__(self, /) | Implement next(self). | | __repr__(self, /) | Return repr(self). | | close(...) | close() -> raise GeneratorExit inside generator. | | send(...) | send(arg) -> send 'arg' into generator, | return next yielded value or raise StopIteration. | | throw(...) | throw(typ[,val[,tb]]) -> raise exception in generator, | return next yielded value or raise StopIteration. | | ---------------------------------------------------------------------- | Data descriptors defined here: | | gi_code | | gi_frame | | gi_running