生成器是一種特殊的迭代器,生成器實現了迭代器協議__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)