一、生成器说明
1、生成器是一个特殊的迭代器。
因为它既没有【__iter__】方法,也没有【__next__】方法。
2、示例1:使用while循环去遍历自定义的生成器对象
def create_num(all_nums):
a, b = 0, 1
current_num = 0
while current_num < all_nums:
yield a
a, b = b, a+b
current_num += 1
obj = create_num(10)
while True:
try:
ret = next(obj)
print(ret)
except Exception as ret:
break
运行结果:
0
1
1
3
5
8
13
21
34
3、示例2:得到生成器的返回值,则调用异常类中【value】可查看。
def create_num(all_nums):
a, b = 0, 1
current_num = 0
while current_num < all_nums:
yield a
a, b = b, a+b
current_num += 1
return "-----ok-----"
obj = create_num(10)
while True:
try:
ret = next(obj)
print(ret)
except Exception as ret:
print(ret.value)
break
运行结果:
0
1
1
3
5
8
13
21
34
-----ok-----
二、send函数
1、说明:除了使用【next】函数可以启动生成器,还可以使用【send】函数启动。
2、特点: 启动生成器后,并且发送数据至生成器中
3、send函数的应用场景:当生成器生成一个新的值时,通过send函数传递一个新的参考值,然后根据这个参考值去做事情。
4、语法:生成器对象.send(参数)
5、查看send函数的执行流程:
第一次调用【next】函数时,程序执行到【yield】关键字处暂停,并将局部变量a的值返回。返回值为:0
第二次调用【send】函数时,程序从上一次【yield】关键字暂停处开始执行,
并将send函数传过来的参数赋值给局部变量ret,然后程序继续往下执行,
直到遇到了yield关键字,程序暂停,并返回yied关键字后面的值给send。
6、代码实现
def create_num(all_nums):
a, b = 0, 1
current_num = 0
while current_num < all_nums:
ret = yield a
print(f"ret的值为:{ret}")
a, b = b, a+b
current_num += 1
obj = create_num(10)
# 使用next函数取值
print(next(obj))
# 使用send函数取值并传入数据:“haha”
print(obj.send("haha"))
运行结果:
0
ret的值为:haha
1
示例2:一开始就使用send会报错
def create_num(all_nums):
a, b = 0, 1
current_num = 0
while current_num < all_nums:
ret = yield a
print(f"ret的值为:{ret}")
a, b = b, a+b
current_num += 1
obj = create_num(10)
# 第一次就使用send函数传值会报错
print(obj.send("haha1"))
print(obj.send("haha2"))
运行结果:
TypeError: can't send non-None value to a just-started generator
报错原因:这是因为第一次执行生成器是从函数内部的第一行代码开始执行的。
而第一行代码中并未设定一个变量来接收send函数传递过来的数据,所以会报错。
解决方法:
第一次启动生成器,使用【next】方法
第一次启动生成器,使用【send】方法,并传递【None】关键字。(一般不使用该方法)