生成器是一种特殊的迭代器,生成器实现了迭代器协议__iter__(),__next__()
python
若是有一亿的数据要咱们处理,咱们经过列表的方式来访问的话,这一亿的数据是存放在内存的,这样会很是的消耗内存的,可是若是咱们使用生成器的话,每当处理一个数据的时候,内存中只是至关于存了一个数据,这样能够节省大量的内存函数
当生成器对象__next__()
的时候,生成器函数会执行到下一个yield,并会返回一个参数code
例一协程
def zx(): yield 1 print(1) if __name__ == '__main__': zx=zx() data=zx.__next__() print(data)
1
例二对象
触发StopIteration异常的两种方式内存
1.迭代完最后一个元素后,触发StopIteration异常generator
def zx(): yield 1 print(1) if __name__ == '__main__': zx=zx() data=zx.__next__() data=zx.__next__()
1 Traceback (most recent call last): File "C:/Users/Administrator/Desktop/01python/研究/生成器/t1.py", line 8, in <module> data=zx.__next__() StopIteration
2.运行生成器函数的时候遇到return,return的值,会成为异常的说明值,如例子的2it
def zx(): yield 1 return 2 print(1) yield 3 if __name__ == '__main__': zx=zx() data=zx.__next__() data=zx.__next__()
Traceback (most recent call last): File "C:/Users/Administrator/Desktop/01python/研究/生成器/t1.py", line 10, in <module> data=zx.__next__() StopIteration: 2
迭代器对象是经过可迭代对象的__iter__()
生成的io
zx=[1,2,3,4,5,6,7,8,9] z1=zx.__iter__()
生成器的建立方式相似生成对象的方式ast
def zx(): for i in range(10): yield i z1=zx()
协程的实现主要就是靠的生成器的send方法
例子1-错误使用
def dog(): print('小乌') while True: food = yield if food == '骨头': yield '好吃' else: yield '旺旺旺' xw = dog() #只是用于返回一个生成器对象,函数并不会执行下去 print(xw.send('骨头'))
出现错误,不能给刚建立的生成器发送非空的值
Traceback (most recent call last): File "C:/Users/Administrator/Desktop/01python/研究/生成器/t5_send.py", line 10, in <module> print(xw.send('骨头')) TypeError: can't send non-None value to a just-started generator
报错信息说不能发送非空的值,那咱们来试试发送一个None会发生什么
print(xw.send(None))
执行成功了
小乌 None
其实也能够用__next__()
也能作到这个打印结果
print(xw.__next__())
结果同样
小乌 None
结论
1.__next__()
的效果其实和send(None)同样
2.yield默认返回None
def dog(): print('小乌') while True: food = yield if food == '骨头': yield '好吃' else: yield '旺旺旺' xw = dog() #只是用于返回一个生成器对象,函数并不会执行下去 print(xw.__next__()) print(xw.send('骨头'))
结果
小乌 None 好吃
结论
1.当生成器刚建立完成,第一次使用先next或者send(None),不能直接send(非空参数)
2.send()有给yield的赋值功能
1.__next__()
的效果其实和send(None)同样
2.当生成器刚建立完成,第一次使用先next或者send(None),不能直接send(非空参数)
3.send()方法就至关于__next__()
和赋值功能的结合
def jishu(): i = 0 while True: zx = yield i if zx == "按一下": i+=1 elif zx == "重置": i=0 js=jishu() print(js.__next__()) print(js.send("按一下")) print(js.send("按一下")) print(js.send("按一下")) print(js.send("按一下")) print(js.send("重置")) print(js.send("按一下")) print(js.send("按一下"))
0 初始化 1 按一下 2 3 4 0 重置 1 2
吃包子
def consumer(name): print(f"{name}老板上包子") while True: baozi = yield print(f"{name}:吃了{baozi}") def producer(): for i in range(2): print('厨师作了两个包子') c1.send(f"肉包{i}") c2.send(f"菜包{i}") c1 = consumer("小黄") c2 = consumer("小乌") c1.__next__() c2.__next__() producer()
小黄老板上包子 小乌老板上包子 厨师作了两个包子 小黄:吃了肉包0 小乌:吃了菜包0 厨师作了两个包子 小黄:吃了肉包1 小乌:吃了菜包1
def zx(n): z,x=0,1 while x < n: yield x z,x = x,z+x z=zx(10) for i in z: print(i)