生成器(generator)就是可迭代对象(它在内部实现了迭代器协议)
生成器在python中的两种表达形式:
生成器表达式
生成器函数
触发生成器的方式:
通过调用__next__()方法,相当于send(None)
通过调用send()方法
2.2 生成器函数
只要函数中包含yield关键字,则此函数就是一个生成器函数
每调用一次 next(),yield后面的值就会被返回一次,且保留此次的状态,下一次调用从此位置开始
1)生成器函数
def func():
print("现在开始执行生成器函数:")
print("First----->")
yield "第一步"
print("Second----->")
yield "第二步"
print("Third")
yield "第三步"
print("End")
yield "生成器函数调用完毕"
f = func()
print(f.next()) # next()函数调用接受到的返回值就是yield后面的值
print(f.next())
print(f.next())
print(f.next())
2)用yield方式的生成器实现字典中文件的内容查找
def get_num():
f = open("population.txt", "r", encoding="utf-8") # 这个文件中的每一行都是一个字典
for i in f:
yield i # 这里返回的 i 为字符串类型
population = eval(get_num().next()) # 这里通过eval()函数重新恢复了文件中数据的数据类型,恢复成了字典
print("%s的人口数为%s" % (population["city"], population["population"]))
注意:生成器只能遍历一次
用生成器表达式的方式实现字典中文件数字的求和
f = open("population.txt", "r", encoding="utf-8")
p = sum(eval(i)["population"] for i in f)
print(p)
3)send()方法的使用
def my_func():
print("First")
send1 = yield 1 # yield后面的值是next方法调用的返回值,而前面的值是yield接收值之后赋值的变量
print("Second")
print("此次send传送的值为:", send1)
send2 = yield 2
print("Third")
print("此次send传送的值为:", send2)
yield 3
print("End")
m = my_func() # 这里并不会执行这个函数,因为只要函数内部定义了yield关键字,函数就变成了生成器,只有通过next方法调用
print(m.next())
print(m.send(None) ) # 这里的send(None),就相当于__next__()方法,触发一次生成器
send()函数将值传递给当前停留位置的yield,之后这个yield会将值传递给前面的变量
print(m.send("这是第二次send"))
4)yield from
yield from可以直接把迭代对象中的每一个数据作为生成器的结果进行返回
因为yield from是将列表中的每一个元素返回,所以写两个yield from并不会产生交替的效果