一、迭代器協議
對象必須提供一個next方法,執行該方法要麼返回迭代中的下一項,要麼就引起一個Stoplteration 異常,終止迭代(只能往後不能往前退)。
二、for循環提高
for循環中,調用對象__iter__()方法,將其變成遵循迭代器協議的迭代對象,再通過其內部的__next__()方法進行依次訪問,從而達到遍歷效果。
三、生成器
可以理解爲數據類型,這種數據類型自動實現了迭代器協議(其他數據類型需要調用自己內置的__iter__方法),生成器就是可迭代對象。
運行生成器方法:
- 生成器函數 __next__()
- python自帶方法:next(生成器)
- .send(參數):生成器函數.send(參數),send中的參數會傳入到當前停止 yield 中。
生成器表現形式:(generatorobject 生成器對象)
- 生成器函數:與常規函數定義相同,但是使用yield返回結果,在每個結果中間掛起函數,以使下次從它離開的地方繼續執行。
- 生成器表達式:類似於列表推導,但是生成器按需產生結果的一個對象,而不是一次構建一個結果列表。
L = [x + 1 for x in range(10)]
print(L)
# 輸出:[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
基本語法:
def 函數名():
yield 返回值
yield 返回值
# yield 特性:與return相同,可以yield多次,可以保存狀態。
yield 語句是生成器中的關鍵語句,生成器在實例化時並不會被執行,而是等待調用其__next__()方法纔開始運行。並且當程序運行完yield語句後就會“吼(hold)住”,即保持當前狀態且停止運行,等待下一次遍歷時才恢復運行,並會把 .send(參數) 中的參數傳回到yield。
生成器案例:生產者、消費者模型(吃包子案例)
# 吃包子
def conSumer(name):
print('我是[%s],準備開始吃包子了!' % name)
while True:
baozi = yield
print('%s 很開心的把 [%s] 吃掉了。' % (name,baozi))
# 生成包子
def producer():
c1 = conSumer('tt')
c1.__next__()
for i in range(10):
c1.send('包子%s' % i)
producer()
執行結果:
我是[tt],準備開始吃包子了!
tt 很開心的把 [包子0] 吃掉了。
tt 很開心的把 [包子1] 吃掉了。
tt 很開心的把 [包子2] 吃掉了。
tt 很開心的把 [包子3] 吃掉了。
tt 很開心的把 [包子4] 吃掉了。
tt 很開心的把 [包子5] 吃掉了。
tt 很開心的把 [包子6] 吃掉了。
tt 很開心的把 [包子7] 吃掉了。
tt 很開心的把 [包子8] 吃掉了。
tt 很開心的把 [包子9] 吃掉了。