1. 生成器
生成器可以理想为一种数据类型,这种数据类型自动实现了迭代器协议(其他数据类型需要调用自己内置的__iter__方法),所以生成器就是可迭代对象。
2. 生成器分类及在python中的表现形式
- 生成器函数:利用常规函数定义,但是,使用yield语句而不是return语句返回结果。yield语句一次返回一个结果,在每个结果中间,挂起函数的运行状态,以便下次从离开的地方继续执行。
1 def test(): 2 yield 1 3 yield 2 4 yield 3 5 res = test() 6 print(next(res)) 7 print(next(res)) 8 print(next(res)) 9 10 """ 11 运行结果: 12 1 13 2 14 3 15 结果分析:下一次next从上一次next返回退出的地方进入 16 """
- 生成器表达式:类似于列表解析,但是,生成器返回按需产生结果的一个对象,而不是一次性构建一个结果列表。
1 test = (item for item in range(4)) 2 print(next(test)) 3 print(next(test)) 4 print(next(test)) 5 6 """ 7 运行结果: 8 0 9 1 10 2 11 结果分析:下一次next从上一次next返回退出的地方进入 12 """
3. 生成器的优点
- 延迟计算。即一次只返回一个结果,也就是说,生成器不会一次性生成所有的结果,这对于大数据量的处理将会非常有用。
- 生成器还能有效地提高代码的可读性。
注意:生成器只能从头到尾遍历一次。
4. 生成器实例1
"人口信息.txt"文件内容:
1 {"name":"北京","population":1600000} 2 {"name":"南京","population":2100000} 3 {"name":"山东","population":2800000} 4 {"name":"山西","population":1800000}
"bin.py"文件内容:
1 def get_information_population(filename): 2 with open(filename) as p: 3 for line in p: 4 res = eval(line) 5 yield res["population"] 6 7 res = get_information_population("人口信息.txt") 8 sum_people = sum(res) 9 for item in res: 10 print(item) 11 12 """ 13 结果分析:执行上面这段代码,将不会有任何输出,这是因为,生成器只能遍历一次。在我们执行sum语句的时候,就已经遍历了一次生成器,从而,在之后当我们再次遍历生成器的时候,将不会有任何记录。所以,上面的代码不会有任何的输出 14 因此,生成器的使用过程中,需要特别注意的就是:生成器只能遍历一次 15 """
5. 生成器实例2
1 def test(): 2 x = "一" 3 print("第一次") 4 print(x) 5 x = yield 1 6 print("第二次") 7 print(x) 8 yield 2 9 10 res = test() 11 print(next(res)) 12 print(res.send("二")) 13 14 """ 15 运行结果: 16 第一次 17 一 18 1 19 第二次 20 二 21 2 22 结果分析:yield 3相当于return控制的是函数的返回值。x = yield的另外一个特征,接受send传过来的值,赋值给x 23 """
6. 生产者——消费者模型
1 import time 2 def consumer(name): 3 print("I am %s, I start to count" %name) 4 while True: 5 num = yield 6 time.sleep(1) 7 print("I am %s, I have counted %s" %(name,num)) 8 def producer(): 9 c1 = consumer("Alix") 10 c2 = consumer("Bob") 11 next(c1) 12 next(c2) 13 for item in range(1,3,1): 14 time.sleep(1) 15 c1.send(item) 16 c2.send(item) 17 producer() 18 19 """ 20 运行结果: 21 I am Alix, I start to count 22 I am Bob, I start to count 23 I am Alix, I have counted 1 24 I am Bob, I have counted 1 25 I am Alix, I have counted 2 26 I am Bob, I have counted 2 27 """