迭代器協議和生成器

迭代器協議

1.迭代器協議是指:對象必須提供一個next方法,執行該方法要麼返回迭代中的下一項,要麼就引發一個StopIteration異常,以終止迭代(只能日後走不能往前退)python

2.可迭代對象:實現了迭代器協議的對象(如何實現:對象內部定義一個__iter__()方法)併發

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

for循環機制

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

for循環就是基於迭代器協議提供了一個統一的能夠遍歷全部對象的方法,即在遍歷以前,先調用對象的__iter__方法將其轉換成一個迭代器,而後使用迭代器協議去實現循環訪問,這樣全部的對象就均可以經過for循環來遍歷了spa

列表,字符串,元組,字典,集合,文件對象等本質上來講都不是可迭代對象,在使用for循環的時候內部是先調用他們內部的__iter__方法,使他們變成了可迭代對象,而後再使用可迭代對象的__next__方法依次循環元素,當元素循環完時,會觸發StopIteration異常,for循環會捕捉到這種異常,終止迭代code

訪問方式常見的有下標方式訪問,迭代器方式訪問,for循環訪問協程

1 下標訪問方式
2 li = [1,2,3,4]
3 print(li[0])#下標訪問
#迭代器協議訪問
li = [1,2,3,4]
f = li.__iter__()#第一步,先經過內部的_iter_方法,先把對象變成可迭代對象
print(f.__next__())#對可迭代對象用_next_方法取值
print(f.__next__())
print(f.__next__())
print(f.__next__())
print(f.__next__())#StopIteration,超出邊界會報錯
#for循環訪問
#for循環l本質就是遵循迭代器協議的訪問方式,先調用diedai_l=l.__iter__()方法,或者直接diedai_l=iter(l),而後依次執行diedai_l.next(),直到for循環捕捉到StopIteration終止循環
li = [1,2,3,4]
for i in li:#li_iter = li._iter_()
    print(i)#li_iter._next_
1 #用while去模擬for循環作的事情
2 diedai_l=l.__iter__()
3 while True:
4     try:
5         print(diedai_l.__next__())
6     except StopIteration:
7         print('迭代完畢了,循環終止了')
8         break

生成器

生成器相似於一種數據類型,這種數據類型自動實現了迭代器協議(其餘的數據類型須要調用本身內置的__iter__方法),因此生成器就是可迭代對象對象

生成器分類及在python中的表現形式:  (python有兩種不一樣的方式提供生成器)blog

1.生成器函數:常規函數定義,可是,使用yield語句而不是使用return語句返回結果.yield語句一次返回一個結果,在每一個結果中間,掛起函數的狀態,以便下次從它離開的地方繼續執行內存

2.生成器表達式:相似於列表推導,可是,生成器返回按需產生結果的一個對象,而不是一次構建一個結果列表,按需取出對象

 

爲什麼使用生成器和生成器的優勢

python使用生成器對延遲操做提供了支持.所謂延遲操做,是指在須要的時候才產生結果,而不是當即產生結果.這也是生成器的主要好處,節省內存

生成器表達式和列表解析

三元表達式:  值1  if  條件  else  值2

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

1 count=[x for x in range(3)]#列表解析

生成器表達式s=(三元表達式)

1 count=(x for x in range(3))#生成器自己就是迭代器,遵循迭代器協議
1 sum(x ** 2 for x in xrange(4))#sum函數是Python的內置函數,該函數使用迭代器協議訪問對象,而生成器實現了迭代器協議,不用畫蛇添足先生成列表

生成器表達式2:yield函數,生成器使用yield語句返回一個值.yield語句掛起該生成器函數的狀態,保留足夠的信息,以便以後從它離開的地方繼續執行

    send():可對yeild函數傳參數,參數會賦值給yield函數前的變量,經過send()可實現僞併發功能

1 1 def count():
2 2     print(1)
3 3     yield ("a")#至關於return,不一樣於return,yield能夠返回多個值
4 4     print(2)
5 5     yield ("b")
6 6 f=count()
7 7 print(f.__next__())#保留當前執行狀態,下次執行從上次狀態處繼續往下執行
8 8 print(f.__next__())
9 9 print(f.__next__())#執行只能一直往前走,不能日後,只能執行一次,執行完繼續執行會觸發StopIteration
1 #僞併發
 2 import time#導入時間模塊
 3 def guke(name):
 4     print("我是%s,我準備吃包子了"%name)
 5     while True:
 6         baozi = yield
 7         time.sleep(1)
 8         print("我是%s,我把包子%s吃掉了"%(name,baozi))
 9 def shengchanzhe(x):
10     xiaofeizhe = guke(x)
11     xiaofeizhe.__next__()
12     for i in range(100):
13         time.sleep(1)
14         xiaofeizhe.send(i)#將i賦值給guke()函數中yield前面的包子,下次執行時今後日後執行
15 use_name = input("歡迎您!怎麼稱呼您:")
16 print("請稍等!包子立刻就給您端上來")
17 shengchanzhe(use_name)

 使用yield實現協程

def f1():
    print(11)
    yield
    print(22)
    yield
    print(33)

def f2():
    print(55)
    yield
    print(66)
    yield
    print(77)

v1 = f1()
v2 = f2()

next(v1) # v1.send(None)
next(v2) # v1.send(None)
next(v1) # v1.send(None)
next(v2) # v1.send(None)
next(v1) # v1.send(None)
next(v2) # v1.send(None)
相關文章
相關標籤/搜索