07-生成器:使用注意
目标¶
- 知道使用 send 方法能够启动生成器、并传递参数
- 能够说出协程中return的作用
1. 生成器中使用return¶
生成器客户以使用return 关键字,语法上没有问题,但是如果执行到 return 语句以后,生成器会停止迭代,抛出停止迭代的异常
In [30]: def fib(n):
....: current = 0
....: num1, num2 = 0, 1
....: while current < n:
....: num = num1
....: num1, num2 = num2, num1+num2
....: current += 1
....: yield num
....: return 'done'
....:
In [31]: F = fib(5)
In [32]: next(F)
Out[32]: 1
StopIteration: done
在使用生成器实现的方式中,我们将原本在迭代器__next__
方法中实现的基本逻辑放到一个函数中来实现,但是将每次迭代返回数值的return换成了yield,此时新定义的函数便不再是函数,而是一个生成器了。{% em color="#2ff700" %}简单来说:只要在def中有yield关键字的 就称为 生成器{% endem %}
此时按照调用函数的方式( 案例中为F = fib(5) )使用生成器就不再是执行函数体了,而是会返回一个生成器对象( 案例中为F ),然后就可以按照使用迭代器的方式来使用生成器了。
....省略代码....
while current_index < n:
# 定义要返回的值
result = a
# 生成新的 a、b值
a, b = b, a+b
# 让当前值+1
current_index += 1
print("-----------2222----------")
yield result
print("-----------3333------------")
return "我是return的内容"
....省略代码....
但是用for循环调用generator时,发现拿不到generator的return语句的返回值。如果想要拿到返回值,必须捕获StopIteration错误,返回值包含在StopIteration的value中:
....省略代码....
# 生成器,生成斐波那契数列
fib = fibonacci(5)
# 第一次没有执行到 return,不用捕获异常
value = next(fib)
print(value)
try:
# 如果无法取得数据,捕获异常
value = next(fib)
print(value)
except StopIteration as e:
print("return信息:%s" % e.value)
2. 使用send唤醒¶
我们除了可以使用next()函数来唤醒生成器继续执行外,还可以使用send()函数来唤醒执行。使用send()函数的一个好处是可以在唤醒的同时向断点处传入一个附加数据。
例子:执行到yield时,gen函数作用暂时保存,返回i的值; temp接收下次c.send("python"),send发送过来的值,c.next()等价c.send(None)
def fibonacci(n):
# 定义斐波那契数列的前2个值
a = 0
b = 1
# 定义当前的位置
current_index = 0
while current_index < n:
# 定义要返回的值
result = a
# 生成新的 a、b值
a, b = b, a+b
# 让当前值+1
current_index += 1
parms = yield result
print("send------", parms)
# 生成器,生成斐波那契数列
fib = fibonacci(5)
# 第一次没有执行到 return,不用捕获异常
# value = next(fib)
# print(value)
value = fib.send(None)
print(value)
value = fib.send("abc")
print(value)
value = fib.send("def")
print(value)
运行结果:
0
send------ abc
1
send------ def
1
Process finished with exit code 0
注意点:
使用send启动生成器的时候传入的参数必须是None,下次启动生成器的时候可以加上参数
提示: 一般第一次启动生成器使用next
总结:
- 可以使用next()函数让生成器从断点处继续执行,即唤醒生成器(函数)
- Python3中的生成器可以使用return返回最终运行的返回值,而Python2中的生成器不允许使用return返回一个返回值(即可以使用return从生成器中退出,但return后不能有任何表达式)。