python生成器
1. 什么是生成器?
生成器(英文名 Generator ),是一个可以像迭代器那样使用for循环来获取元素的函数。
生成器的出现(Python 2.2 +),实现了延时计算,从而缓解了在大量数据下内存消耗过猛的问题。
当你在 Python Shell 中敲入一个生成器对象,会直接输出 generator object 提示你这是一个生成器对象
>>> gen = (i for i in range(5))
>>> gen
at 0x10cae50b0>
2. 如何创建生成器?
使用列表推导式
在上面已经演示过,正常我们使用列表推导式时是下面这样子,使用 [] ,此时生成的是列表。
>>> mylist = [i for i in range(5)]
>>> mylist
[0, 1, 2, 3, 4]
而当你把 [] 换成 () ,返回的就不是列表了,而是一个生成器
>>> gen = (i for i in range(5))
>>> gen
at 0x10cae50b0>
使用 yield
yield 是什么东西呢? 它相当于我们函数里的 return,但与 return 又有所不同。
当一个函数运行到 yield 后,函数的运行会暂停,并且会把 yield 后的值返回出去。
若 yield 没有接任何值,则返回 None
yield 虽然返回了,但是函数并没有结束
请看如下代码,我定义了一个 generator_factory 函数,当我执行 gen = generator_factory() 时,gen 就是一个生成器对象
>>> def generator_factory(top=5):
... index = 0
... while index < top:
... print("index 值为: " + str(index))
... index = index + 1
... yield index
... raise StopIteration
...
>>> gen = generator_factory()
>>> gen
3. 生成器的使用
从一个生成器对象中取出元素,和我们前面学过的通过切片访问列表中的元素不一样,它没有那么直观。
想要从生成器对象中取出元素,只有两种方法:
第一种方法:使用 next 方法一个一个地把元素取出来,如果元素全部取完了,生成器会抛出 StopIteration 的异常。
>>> gen = (x for x in range(3))
>>> gen
at 0x1072400b0>
>>> next(gen)
0
>>> next(gen)
1
>>> next(gen)
2
>>> next(gen)
Traceback (most recent call last):
File "", line 1, in
StopIteration
第二种方法:使用 for 循环一个一个地迭代出来
>>> gen = (x for x in range(3))
>>> for i in gen:
... print(i)
...
0
1
2
4. 生成器的激活
生成器对象,在创建后,并不会执行任何的代码逻辑。
想要从生成器对象中获取元素,那么第一步要触发其运行,在这里称之为激活。
方法有两种:
使用next() :上面已经讲过
使用generator.send(None)
还以下面这段代码为例,可以看到 gen.send(None) 相当于执行了 next(gen)
>>> def generator_factory(top=5):
... index = 0
... while index < top:
... print("index 值为: " + str(index))
... index = index + 1
... yield index
... raise StopIteration
...
>>>
>>> gen = generator_factory()
>>> gen.send(None)
index 值为: 0
1
>>> gen.send(None)
index 值为: 1
2
5. 生成器的状态
生成器在其生命周期中,会有如下四个状态
GEN_CREATED # 生成器已创建,还未被激活
GEN_RUNNING # 解释器正在执行(只有在多线程应用中才能看到这个状态)
GEN_SUSPENDED # 在 yield 表达式处暂停
GEN_CLOSED # 生成器执行结束
通过下面的示例可以很轻松地理解这一过程(GEN_RUNNING 这个状态只有在多线程中才能观察到,这里就不演示啦)
>>> gen = (x for x in range(2))
>>> from inspect import getgeneratorstate
>>> gen = (x for x in range(3))
>>> getgeneratorstate(gen)
'GEN_CREATED'
>>>
>>> next(gen)
0
>>> getgeneratorstate(gen)
'GEN_SUSPENDED'
>>> next(gen)
1
>>> next(gen)
Traceback (most recent call last):
File "", line 1, in
StopIteration
>>> getgeneratorstate(gen)
'GEN_CLOSED'
6. 生成器的异常
在最前面,我有定义了一个生成器函数。
def generator_factory(top=2):
index = 0
while index < top:
index = index + 1
yield index
raise StopIteration
在没有元素可返回时,我最后抛出了 StopIteration 异常,这是为了满足生成器的协议。
实际上,如果你不手动抛出 StopIteration,在生成器遇到函数 return 时,会我自动抛出 StopIteration。
请看下面代码,我将 raise StopIteration 去掉后,仍然会抛出异常。
>>> def generator_factory(top=2):
... index = 0
... while index < top:
... index = index + 1
... yield index
...
>>> gen = generator_factory()
>>> next(gen)
1
>>> next(gen)
2
>>> next(gen)
Traceback (most recent call last):
File "", line 1, in
StopIteration
审核编辑:符乾江
-
生成器
+关注
关注
7文章
322浏览量
22499 -
python
+关注
关注
57文章
4856浏览量
89550
发布评论请先 登录
如何通过地址生成器实现神经网络特征图的padding?
非对称密钥生成和转换规格详解
PanDao:实际约束条件下成像系统的初始结构的生成
EB Tresos验证步骤失败是什么原因?
使用s32ds软件时,无法生成是怎么回事?
“Quantum Origin”成首个获NIST验证的软件量子随机数生成器
EB Tresos状态显示无法运行生成器是什么原因导致的?
S32G399 GoldVIP网关执行失败的原因?
DS855调相直接数字合成器适合哪些场景?
敏捷合成器的技术原理和应用场景
Python中的迭代器与生成器
开源随机数生成器库OpenRNG助力实现移植到Arm平台时的最佳性能
labview正版购买
超详细!FMU生成器用户手册来啦~

python生成器是什么
评论