Python中的迭代器、生成器——10

什麼是迭代器

迭代器即迭代的工具python

迭代是一個重複的過程,每一次重複即一次迭代,且每次迭代的結果都是下一次迭代的初始值編程

while True:    #這裏只是單純的重複,不是迭代
    print('-----')
l = [1,2,3]
count = 0

while count <= len(l):   #這裏是迭代
    print(l[count])
    count += 1

迭代器協議

一、迭代器協議是指:對象必須提供一個next方法,執行該方法要麼返回迭代中的下一項,要麼就引發一個StopIteration異常,以終止迭代app

二、可迭代對象:實現了迭代器協議的對象(對象內部定義一個__iter__()方法)函數

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

 

 

對於序列類型,如:字符串、列表元組等,咱們可使用索引的方式迭代取出其包含的元素,可是對於無序類型:字典,集合,文件等是沒有索引的,因此咱們要想取出其內部包含的元素,則必須找出一種不依賴於索引的方式spa

 

可迭代對象指的是有內置方法__iter__的對象:code

'hello'.__iter__
(1,2,3).__iter__
[1,2,3].__iter__
{'a':1}.__iter__
{'a','b'}.__iter__
{'a','b'}.__iter__
open('a.txt').__iter__

 

可迭代對象執行obj.__iter()獲得的結果就是迭代器對象對象

而迭代器對象指的是即內置有__iter__又內置有__next__方法的對象blog

文件類型是迭代器對象索引

open('a.txt').__iter__
open('a.txt').__next__

迭代器對象必定是可迭代對象,而可迭代對象不必定是迭代器對象

dic = {'a':1,'b':2,'c':3}    
iter_dic = dic.__iter__()  #獲得迭代器對象,迭代器對象即有__iter__又有__next__,可是迭代器.__iter__()獲得的仍然是迭代器自己
iter_dic.__iter__() is iter_dic  #True

print(iter_dic.__next__())#next(iter_dic)
print(iter_dic.__next__())#next(iter_dic)
print(iter_dic.__next__())#next(iter_dic)
#print(iter_dic.__next__())#拋出異常StopIteration,結束

iter_dic = dic.__iter__()
while 1:
    try:
        k = next(iter_dic)
        print(dicp[k])
    except StopIteration:
        break

for循環

dic = {'a':1,'b':2,'c':3}
for k in dic:
    print(dic[k])
#for循環的工做原理
#一、執行in後對象的dic.__iter__()方法,獲得一個迭代器對象iter_dic
#二、執行next(iter_dic),將獲得的值賦值給k,而後執行循環代碼體
#三、重複過程2,直到捕捉到異常StopIteration,結束循環

迭代器的優缺點

優勢:

體格一種統一的、不依賴於索引的迭代方式

惰性計算,節省內存

缺點:

沒法獲取長度(只有在next完畢後才知道到底有幾個值)

一次性的,只能日後走,不能往前退

 

 

生成器

只要函數內部包含有yield關鍵字,那麼函數名()獲得的結果就是生成器,而且不會執行函數內部代碼

def test():
    yield 1
    yield 2
    yield 3

print(test)#結果是:<function test at 0x01E79D68>
test().__next__()

yield:

把函數作成迭代器

對比retrun,能夠返回多個值,能夠掛起/保存函數的運行狀態

yield關鍵字的另外一種使用形式,表達式形式yield

def eater(name)
    print('%s 準備吃飯了' %name)
    food_list = []
    while True:
        food = yield food_list
        print('%s 吃了 %s' %(name,food))
        food_list.append(food)

g = eater('egon')
g.send(None)
g.send('蒸羊羔')
g.send('蒸鹿茸')
g.send('蒸熊掌')
g.send('燒素鴨')
g.colse()
g.send('燒素鵝')
g.send('燒鹿尾')

 

 

 

生成器就是迭代器

a.__iter__
a.__next__
res = next(a)
print(res)

 

生成器表達式

列表解析

a = ['jidan %s' %i for i in range(10)]

把列表解析的[]換成()獲得的就是生成器表達式

a1 = ('jidan %s' %i for i in range(10))

列表解析與生成器表達式都是一種便利的編程方式,只不過生成器表達式更節省內存

python使用迭代器協議讓for循環變得更加通用,大部份內置函數,也是使用迭代器協議訪問對象的,例如sum函數是python的內置函數,該函數使用迭代器協議訪問對象,而生成器實現了迭代器協議,因此咱們能夠直接這樣計算一系列值的和:

s = sum(x ** 2 for x in range(10))
print(s)
#結果是:285

而不須要先構建一個列表:

sum = ([x ** 2 for x in range(10)])
相關文章
相關標籤/搜索