python-----迭代器協議和生成器


迭代器協議和生成器

迭代器協議:

1、迭代器協議是指:對象必須提供一個next()方法,執行該方法要么返回迭代中的下一項,要么引起一個StopIteration異常,以終止迭代(只往后走,不能往前退----》模擬人更新換代)

2、可迭代對象:實現可迭代協議的對象。(對象內部定義一個__iter__()方法)

3、協議是一種約定,可迭代對象實現了可迭代協議,python的內部工具(如for sum max min...函數)使用迭代器 協議訪問對象。

for循環機制:

for循環的本質:循環所有對象,全部都使用迭代器協議。

for循環就是基於迭代器協議提供了一個統一的可遍歷所有對象的方法,即在遍歷之前,先調用對象的__iter__()方法將其轉換為一個迭代器,然后使用迭代器協議去實現循環訪問,這樣所有對象都可以通過for循環來遍歷了。

列表、字符串、元組、字典、集合、文件對象等本質上都不是可迭代對象,在使用for循環時內部先調用他們內部的__iter__方法,使它們變為一個可迭代對象,然后使用可迭代對象的next(可迭代對象)方法或者 對象.__next__(),依次循環元素,當元素循環完時,會觸發StopIteration異常,for循環會捕捉到這種異常,終止迭代。

訪問方式:下標方式、迭代器協議、for循環:

下標:

1 # _*_ encoding:utf-8 _*_
2 __author__ = 'listen'
3 __date__ = '2018/11/19 22:10'
4 # li=[1,2,3,4,5]  #通過下標索引方式取   只試用於有序的 列表 元組 字符串  不適用無序字典 集合
5 # print(li[0])  #1
6 # print(li[1])  #2
7 # print(li[2])  #3

 迭代器協議:

 1 #通過迭代器訪問
 2 # li=[1,2,3,4,5,6]
 3 # iter_li=li.__iter__()  #通過__iter__()方法 生成一個可迭代對象
 4 # print(iter_li.__next__())  #1  可迭代對象就有__next__()方法  一個一個取值
 5 # print(iter_li.__next__())  #2
 6 # print(iter_li.__next__())  #3
 7 # print(iter_li.__next__())
 8 # print(iter_li.__next__())
 9 # print(iter_li.__next__())
10 # print(iter_li.__next__())  #StopIteration,超出邊界報錯

for循環訪問:

 1 #for 循環訪問的本質==遵循迭代器訪問方式,先調用iter_l=li.__iter__()方法,然后依次執行iter_l.__next__(),直到for循環捕捉到StopIteration終止循環
 2 # li=[1,2,3,4,5]
 3 # for i in li:
 4 #     print(i)
 5 
 6 
 7 #用while去模擬for循環做的事情
 8 # li=[1,2,3,4,5]
 9 # index=0
10 # while index<len(li):
11 #     print(li[index])
12 #     index+=1
13 
14 
15 #next()和__next__()方法是相同的
16 # li=[1,2,3]
17 # iter_li=li.__iter__()
18 # print(iter_li.__next__())  #1
19 # print(next(iter_li))   #2

生成器

定義:生成器類似於一種數據類型,這種數據類型自動實現迭代器協議(其他的數據類型都需要調用自身的__iter__方法),所以生成器就是可迭代對象。

1、生成器函數:和常規函數沒什么區別,但使用yield語句返回結果 而不是return,yield語句一次返回一個結果,但每個結果中間,掛起函數的狀態,以便下次從它離開的地方繼續執行。

2、生成器表達式:類似於列表推導式,但是生成器返回按需產生的結果的一個對象(類似內存的一個地址),而不是一次構建結果的列表,按需取對象。

使用生成器的優點:

python使用生成器對延遲操作提了支持。所謂延遲操作,是指需要的時候才產生結果,而不是立即產生結果,節省內存,運行效率高,這是生成器的主要好處。

生成器表達式和列表表達式

三元表達式:f=if取出的結果 if條件  else  else結果

列表解析:s=[三元表達式],列表解析生成的是一個真實存在的列表,對於比較大的列表,消耗內存比較大。

count=[x for x in range(3)]

生成器表達式1:s=(三元表達式),區別於列表解析是 [] 到 ()

 

count=(x for x in range(3))  #生成器本身就是迭代器,遵循迭代器協議

 

 1 #生成器----一種數據類型,這種數據類型自動實現迭代器協議(其他數據類型(字典 list tuple等等)都需要調用內置的__iter__()方法),所以生成器就是可迭代對象
 2 
 3 
 4 #1、生成器函數  yield 代替return語句返回  可以調用多次
 5 # def fun():
 6 #     yield 1  #可迭代對象
 7 #     yield 2
 8 #     yield 3
 9 # f=fun()
10 # print(f.__next__())  #1
11 # print(f.__next__())  #2
12 # print(f.__next__())  #3
13 # print(f.__next__()) ##執行只能一直往前走,不能往后,只能執行一次,執行完繼續執行會觸發StopIteration
14 
15 
16 
17 #2、生成器表達式
18 #三元表達式  result=值1  if 條件  else 值2  列表表達式=[]是真實存在內存中的列表,對於大的列表特別消耗內存
19 # count=[x for x in range(3)]    #三元表達式
20 # count=(x for x in range(3))  #生成器
21 # sum(x for x in range(3)) ##sum函數是Python的內置函數,該函數使用迭代器協議訪問對象,而生成器實現了迭代器協議,不用多此一舉先生成列表
22 
23 #雞下蛋
24 laomuji=('雞蛋%s'%i  for i in range(9) if i<5)
25 print(laomuji) #<generator object <genexpr> at 0x00000221029D1C50>  這是一個可迭代對象就不會占用很大的內存
26 print(laomuji.__next__())
27 print(laomuji.__next__())
28 print(laomuji.__next__())
29 print(laomuji.__next__())
30 print(laomuji.__next__())
31 print(next(laomuji))  #StopIteration拋異常

 生成器只能往后走,不能往前退,且只能執行一次。

 1 # _*_ encoding:utf-8 _*_
 2 __author__ = 'listen'
 3 __date__ = '2018/11/20 21:14'
 4 # #執行只能一直往前走,不能往后,只能執行一次
 5 # def test():
 6 #     for i in range(4):
 7 #         yield i
 8 # t=test()
 9 # t1=(i for i in t)
10 # t2=(i for i in t1)
11 # print(list(t1))   #list()就是在執行next方法  for也是在執行next方法  [0, 1, 2, 3]
12 # print(list(t2))  #  []  t1的數據取完了,沒有了,所以list(t2)為空

 


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
  © 2014-2022 ITdaan.com 联系我们: