迭代器即迭代的工具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
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)])