1、定義
(1)迭代器協議:對象必須提供一個next()方法,執行該方法要麼返回迭代中的下一項,要麼就引起一個StopIteration異常,以終止迭代
(2)可迭代對象:實現了迭代器協議的對象(如何實現?對象內部定義了一個_iter_()方法)
(3)協議是一種約定,可迭代對象實現了迭代器協議,python的內部工具(如for循環、sum、min、max函數等)使用迭代器協議訪問對象
2、for循環的本質
循環所有對象,全都是使用迭代器協議
3、疑點
for循環的本質是遵循迭代器協議去訪問對象,那麼for循環的對象肯定都是迭代器了啊,那for循環可以遍歷字符串、列表、、字典、集合文件對象,那麼這些類型的數據肯定都是可迭代對象嗎?但是,列表中沒有next()方法,爲什麼?
解答:以上for循環遍歷那些不是可迭代對象,只不過在for循環式,調用了他們內部的_iter_方法,把他們變成了可迭代對象
然後for循環調用可迭代對象的_next_()方法,捕捉Stoplteration異常,以終止迭代,有個自帶的內置方法,next()方法,是一樣的。
4、三元表達式
(1)表達式結構:if成立的返回值 + if判斷 + else if不成立的返回值
(2)注意:元就是運算符的意思,可以小於等於三元,不能超過三元
5、生成器
(1)什麼是生成器?
可以理解爲一種數據類型,這種數據類型自動實現了迭代器協議(其他的數據類型需要調用自己內置的_iter_方法),所以生成器是可迭代對象
(2)生成器在python中的表現形式
- 生成器函數:常規定義函數,使用的是yeild語句返回而不是return返回,yeild語句每次返回一個結果,在每個結果中間,掛起函數的狀態,以便下次從它離開的地方繼續執行
- 生成器表達式:類似於列表推導,但是,生成器但會按需生產的一個對象,而不是一次構建一個結果列表
(3)生成器特點: - 是可迭代對象
- 實現了延遲計算,一次返回一個結果,提高代碼可讀性
- 代碼簡潔,佔空間小,節省內存地址
- 生成器本質和其他的數據類型一樣,都是實現了迭代器協議,只不過生成器附加了一個延遲計算內存的好處,其餘的可迭代對象沒有這點好處
- 生成器只能遍歷一次
- 可以保留函數狀態
- 效率高(回想老母雞下蛋實例,下一個賣一個)
6、列表解析
列表解析使代碼更簡潔,舉例如下:
(1)不用列表解析的代碼:
l=[]
for i in range(10):
l.append("雞蛋%s"%i)
print(l)
#輸出結果:
['雞蛋0', '雞蛋1', '雞蛋2', '雞蛋3', '雞蛋4', '雞蛋5', '雞蛋6', '雞蛋7', '雞蛋8', '雞蛋9']
(2)用列表解析的代碼:
l=["雞蛋%s"%i for i in range(10)]
print(l)
#輸出結果:同上
(3)還可以加判斷:
l=["雞蛋%s"%i for i in range(10) if i > 5]
print(l)
#輸出結果:
['雞蛋6', '雞蛋7', '雞蛋8', '雞蛋9']
(4)沒有四元表達式,不可以放太多
l=["雞蛋%s"%i for i in range(10) if i > 5 else i]
print(l)
#說明:else i 是錯誤的
(5)把列表解析的[]換成()得到的就是生成器表達式
7、生產者消費者模型實例—輸送4個包子,現做現吃
import time
def consumer(name):
print("我是【%s】,我要開始吃包子了"%name)
while True:
baozi=yield
time.sleep(1)
print("【%s】很開心的把【%s】吃掉了"%(name,baozi))
def producer():
c1=consumer("Test1")
c2=consumer("Test2")
c1.__next__()
c2.__next__()
for i in range(4):
time.sleep(1)
c1.send("包子%s"%i)
c2.send("包子%s"%i)
producer()
#輸出結果:
我是【Test1】,我要開始吃包子了
我是【Test2】,我要開始吃包子了
【Test1】很開心的把【包子0】吃掉了
【Test2】很開心的把【包子0】吃掉了
【Test1】很開心的把【包子1】吃掉了
【Test2】很開心的把【包子1】吃掉了
【Test1】很開心的把【包子2】吃掉了
【Test2】很開心的把【包子2】吃掉了
【Test1】很開心的把【包子3】吃掉了
【Test2】很開心的把【包子3】吃掉了
注意:
(1)觸發生成器運行的第三種情況send(None)。
(2)當yeild被賦值的時候,send的參數就是yeild的返回值,每次執行以yeild結束。
作業解讀:
(1)所有能用遞歸解決的問題都可以用for循環來解決
(2)break、contine、 return區別
- break結束當前循環
- continue結束本次循環進入下一循環
- return結束函數,並返回結果,默認爲None
(3)Python 3 中的range函數和Python 2.7中的range函數有什麼區別? - 3.x range不會生成值,只有用的時候纔會生成
- 2.7 range會生成一個列表,值已經生成