文章目录
什么是生成器
如下代码所示,列表生成式只是生成了一个列表,并将此列表对象的内存地址赋值给变量。而生成器则是生成一个“generator object”,无论有再多元素都只占用一个很小的空间。当需要使用的时候再行进行计算,而且是计算一个就用一个,用完后即清理相关的内存空间。 这种并不是一次性计算好,而是在使用过程中计算一个用一个的方式就叫生成器(generator).
a = [i for i in range(10)]
print(a)
"""
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
"""
b = (i for i in range(10))
print(b)
"""
<generator object <genexpr> at 0x030D3370>
"""
创建生成器(generator)的方法
- 把一个列表生成式的[]改成(),即可创建一个生成器。
- 使用“yield”
生成器元素的查看(next())
在python3中,对于生成器有一个内置方法“next()”,用于单次计算元素,计算完成后并使用完成后,从生成器对象中删除,下次再调用“next()”方法时即计算下一个元素,计算完成后并使用。如下如示:
b = (i for i in range(10))
print(b)
"""
<generator object <genexpr> at 0x030D3370>
"""
print(b.__next__()) #计算第一个元素并使用,此处的使用方法是打印
print(b.__next__()) #计算第二个元素并使用,此处的使用方法是打印
print(b.__next__()) #计算第三个元素并使用,此处的使用方法是打印
print(b.__next__()) #计算第四个元素并使用,此处的使用方法是打印
print(b.__next__()) #计算第五个元素并使用,此处的使用方法是打印
"""
<generator object <genexpr> at 0x02D93370>
0
1
2
3
4
"""
如上,并不像列表一样,列表是固定存储在内存中,通过下标可随意调用相应下标的值,而使用“next()”方法调用生成器对象时,调用完,下次不再进行计算。
生成器元素的查看(使用built-in内置函数next())
b = (i for i in range(10))
print(b)
"""
<generator object <genexpr> at 0x030D3370>
"""
print(b.__next__()) #计算第一个元素并使用,此处的使用方法是打印
print(b.__next__()) #计算第二个元素并使用,此处的使用方法是打印
print(next(b)) #计算第三个元素并使用,此处的使用方法是打印
print(next(b)) #计算第四个元素并使用,此处的使用方法是打印
print(next(b)) #计算第五个元素并使用,此处的使用方法是打印
print(next(b)) #计算第六个元素并使用,此处的使用方法是打印
"""
<generator object <genexpr> at 0x00B33370>
0
1
2
3
4
5
"""
next()是python的一个内置函数,而“next()”是生成器对象的一个内置方法。两者并无太大差别,从现象上看并无 差别,而next()是python的内置函数,所以在版本过渡时较平滑。
生成器元素的遍历(for循环)
b = (i for i in range(10))
print(b)
"""
<generator object <genexpr> at 0x030D3370>
"""
for i in b:
print(i)
"""
<generator object <genexpr> at 0x015A3370>
0
1
2
3
4
5
6
7
8
9
"""
yield 创建生成器
使用yield关键写来创建生成器,创建的格式与定制函数一样,
def generator():
print("first.")
yield "OK1"
print("Secondary.")
yield "OK2"
firstg = generator()
print(firstg)
"""
<generator object generator at 0x034A18B0>
"""
yield 与 return的区别
Python在函数定义中 使用return用于返回值,且一旦遇到return 函数体就执行完毕;
而生成器generator的函数,在每次使用next()进行调用后遇到yield语句后返回,但是计算并使用完成后会保存当前的位置,下次会再次从yield处进行执行。
next() | __next__()方法计算并使用yield创建的生成器元素
def generator():
print("first.")
yield "OK1"
print("Secondary.")
yield "OK2"
firstg = generator()
print(firstg)
print(firstg.__next__())
print(firstg.__next__())
"""
<generator object generator at 0x035F1728>
first.
OK1
Secondary.
OK2
"""
send() 向yield中传入相关数据
send()与next() 方法一样,都可以计算并使用数据,但是send()多一个功能就是可以发送一个值给变量。并不是赋值给yield,而是赋值给前面的变量。
第一次进入,并不能直接使用send赋值,可以使用send(None)或者使用next() 先调用计算一次。
需要特别注意的是,send()方法与next()方法一样,会让生成器进行一次计算,并将值返回。且不要以为send只单独只发送一次值,
def generator():
print("Before.")
sequence = yield "OK1"
print(sequence)
yield "OK2"
# return None
firstg = generator()
print(firstg)
a = next(firstg)
print(a)
b = firstg.send("This is test value.")
print(b)
"""
<generator object generator at 0x00731798>
Before.
OK1
This is test value.
OK2
"""