1、生成器
迭代器每次使用next()
可以获取到按照规律生成的数据,但是在构造迭代器时需要自己记录状态,很麻烦,于是我们用更简便构造语法——即生成器(generator)。生成器是一类特殊的迭代器。
2、创建生成器的方法1
把一个列表生成式的[ ]
改成 ( )
In [0]: L = [ x*2 for x in range(5)]
In [1]: G = ( x*2 for x in range(5))
In [2]: G
Out[2]: <generator object <genexpr> at 0x7f626c132db0>
G 是一个生成器。我们可以直接打印出列表L的每一个元素,而对于生成器G,我们可以按照迭代器的使用方法来使用,即可以通过next()函数
、for循环
、list()
等方法使用。
3、创建生成器的方法2
只要在def
中有yield
关键字的 就称为 生成器
def gen(s):
for i in range(s):yield s-i
a=gen(5)
print(next(a))
print(next(a))
b=gen(6)
print(next(b))
print(next(b))
此时按照调用函数的方式a = gen(5)
使用生成器就不再是执行函数体了,而是会返回一个生成器对象a,然后就可以按照使用迭代器的方式来使用生成器了。
4、解释
yield
的作用:保存当前运行状态(断点),然后暂停执行,将yield关键字后面表达式的值作为返回值返回,此时可以理解为起到了return的作用。- 可以使用
next()
函数让生成器从断点处继续执行,即唤醒生成器(函数)。 - Python3中的生成器可以使用
return
返回最终运行的返回值,而Python2中的生成器不允许使用return返回一个返回值(即可以使用return
从生成器中退出,但return
后不能有任何表达式)。
def gen(s):
for i in range(s):
yield s-i
return "ok..."
a=gen(5)
while True:
try:print(next(a))
except StopIteration as e:
print(e.value)
break
4、使用send
唤醒
我们除了可以使用next()
函数来唤醒生成器继续执行外,还可以使用send()
函数来唤醒执行。使用send()
函数的一个好处是可以在唤醒的同时向断点处传入一个附加数据。
例子:
执行到yield
时,gen
函数作用暂时保存,返回i的值;
temp
接收下次a.send("python")
send()
发送过来的值,a.__next__()
等价a.send(None)
def gen():
i = 0
while i<5:
temp = yield i
print(temp)
i+=1
a=gen()
next(a)
print(a.send("你好"))
5、个人总结
- 函数只要有
yield
就算是生成器的模板 yield
相当于挂起该函数【将对象实例化保存值】- 创建生成器对象后,生成器并不会立即运行,当通过
next(对象名)
或对象名.__next__()
启动首次运行,运行到yield
暂停。 对象名.send(数据)
可以传递一个数据到暂停的生成器中,需要注意,send
函数不能用来启动生成器。- 生成器暂停后,
对象名.send(None)
等价于next(对象名)
等价于对象名.__next__()