Python之三元表達式、迭代器、生成器---第十一天

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會生成一個列表,值已經生成
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章