一:迭代器python
1.什麼是迭代?linux
1.重複 2.下一次重複是基於上一次的結果數據結構
# l=['a','b','c','d'] # count=0 # while count < len(l): # print(l[count]) #count的值基於上一次結果,因此是迭代
# count+=1
2.迭代器協議app
指:對象必須提供一個next方法,執行該方法要麼返回迭代中的下一項,要麼就引發一個StopIteration異常,以終止迭代 (只能日後走不能往前退)。ide
迭代器的優勢:
1.提供了一種不依賴索引的迭代方式
2.惰性計算,節省內存
迭代器的缺點:
1.取值不如按照索引取值的方便
2.只能前進,不能後退
3.沒法獲取長度函數
判斷是否爲可迭代對象或者迭代器對象的方法:測試
# # from collections import Iterable,Iterator # # print(isinstance(g,Iterator)) #可判斷是夠爲迭代器對象
# def countdown(n): # print('starting countdown') # # while n > 0: # yield n # n-=1 # print('stop countdown') # g=countdown(5)
# print(g.__next__()) # print(g.__next__()) # for i in g: # print(i)
3 迭代器spa
在介紹迭代器以前,咱們先來了解一下容器這個概念。code
容器是一種把多個元素組織在一塊兒的數據結構,容器中的元素能夠逐個地迭代獲取。簡單來講,就比如一個盒子,咱們能夠往裏面存放數據,也能夠從裏面一個一個地取出數據。在python中,屬於容器類型地有:list,dict,set,str,tuple.....。容器僅僅只是用來存放數據的,咱們日常看到的 l = [1,2,3,4]等等,好像咱們能夠直接從列表這個容器中取出元素,但事實上容器並不提供這種能力,而是可迭代對象賦予了容器這種能力。對象
說完了容器,咱們在來談談迭代器。迭代器與可迭代對象區別在於:__next__()方法。
咱們能夠採用如下方法來驗證一下:
from collections import Iterator f = open('a.txt') i = 1 s = '1234' d = {'abc':1} t = (1, 2, 344) m = {1, 2, 34, } print(isinstance(i,Iterator)) print(isinstance(s,Iterator)) print(isinstance(d,Iterator)) print(isinstance(t,Iterator)) print(isinstance(m,Iterator)) print(isinstance(f,Iterator)) ########輸出結果########## False False False False False True
結果顯示:除了文件對象爲迭代器,其他均不是迭代器
下面,咱們進一步來驗證一下:
print(hasattr(i,"__next__")) print(hasattr(s,"__next__")) print(hasattr(d,"__next__")) print(hasattr(t,"__next__")) print(hasattr(m,"__next__")) print(hasattr(f,"__next__")) #######結果########### False False False False False True
從輸出結果能夠代表,迭代器與可迭代對象僅僅就是__next__()方法的有無。
'模擬linux中' #tail -f a.txt import time def tail(filepath,encoding='utf-8'): with open(filepath,encoding=encoding) as f: f.seek(0,2) while True: line=f.readline() if line: print(line,end='') # yield line else: time.sleep(0.5) tail('b.txt') # for i in g: # print(i) #tail -f a.txt |grep 'error' # def grep(lines,pattern): # for line in lines: # if pattern in line: # # print(line,end='') # yield line # g=tail('a.txt') # print(g) # grep(g,'error') # tail -f a.txt |grep 'error' |grep '404' # g1=tail('a.txt') # g2=grep(g1,'error') # g3=grep(g2,'404') # for i in g3: # print(i)
Tips:(字符串,列表,元組,字典,集合,文件對象)這些都不是可迭代對象,只不過在for循環式,調用了他們內部的__iter__方法,把他們變成了可迭代對象,
而後for循環調用可迭代對象的__next__方法去取值,並且for循環會捕捉StopIteration異常,以終止迭代.
StopIteration異常:.__nex___執行後若是沒有返回值就會報此異常。
for item in g: print(item) ###for執行in後面的對象g下面的.__iter__方法,獲得一個迭代器k,而後for循環自動k.__next__一次,將獲得的結果賦值給item.而後再iter一次變成迭代器賦值給item,直到沒有值輸出,出現stopiteration異常,for循環能夠捕捉到這個異常,而後終止這個循環。
for item in 8:
print(item)
============結果================
TypeError:'int' object is not iterable ###數字是不可迭代對象,下面沒有.__iter__方法,因此報錯。
Try 可檢測異常:
l={'a':1,'x':2,'w':3,'z':4} l=l.__iter__() #轉換成迭代器
while True: try: #捕捉異常,檢測其下縮進的語句是否有異常
i=l.__next__() print(i) except StopIteration: #except檢測異常
break
二:生成器(生成器的本質就是迭代器)
1.什麼是生成器
能夠理解爲一種數據類型,這種數據類型自動實現了迭代器協議(其餘的數據類型須要調用本身內置的__iter__方法),因此生成器是可迭代對象。
按照咱們以前所說的,迭代器必須知足兩個條件:既有__iter__(),又有__next__()方法。那麼生成器是否也有這兩個方法呢?答案是,YES。具體來經過如下代碼來看看。
def func(): print("one------------->") yield 1 print("two------------->") yield 2 print("three----------->") yield 3 print("four------------>") yield 4 print(hasattr(func(),'__next__')) print(hasattr(func(),'__iter__')) #########輸出結果########### True True
Python有兩種不一樣的方式提供生成器:
1.函數體內包含有yield關鍵字,該函數的執行結果是生成器(generator).可是,使用yield語句而不是return語句返回結果。yield語句一次返回一個結果,在每一個結果中間,掛起函數的狀態,以便下次重它離開的地方繼續執行.
2.生成器表達式:相似於列表推導,可是,生成器返回按需產生結果的一個對象,而不是一次構建一個結果列表
既然生成器就是迭代器,那麼咱們是否是也能夠經過for循環來遍歷出生成器中的內容呢?看下面代碼.
def func(): print("one------------->") yield 1 print("two------------->") yield 2 print("three----------->") yield 3 print("four------------>") yield 4 for i in func(): print(i) #########輸出結果######## one-------------> 1 two-------------> 2 three-----------> 3 four------------> 4
很顯然,生成器也能夠經過for循環來遍歷出其中的內容。
下面咱們來看看生成器函數執行流程:
def func(): print("one------------->") yield 1 print("two------------->") yield 2 print("three----------->") yield 3 print("four------------>") yield 4 g = func() # 生成器 == 迭代器 print(g.__next__()) print(g.__next__()) print(g.__next__()) print(g.__next__())
每次調用g.__next__()就回去函數內部找yield關鍵字,若是找獲得就輸出yield後面的值而且返回;若是沒有找到,就會報出異常。上述代碼中若是在調用g.__next__()就會報錯。Python使用生成器對延遲操做提供了支持。所謂延遲操做,是指在須要的時候才產生結果,而不是當即產生結果。這也是生成器的主要好處。
生成器就是迭代器,只能前進不能後退,咱們看下這個例子:
#生成器函數補充 # def countdown(n): # while n > 0: # yield n # n-=1 # # g=countdown(5) # print(g.__next__()) # print(g.__next__()) # # print('='*20) # for i in g: # print(i) # # print('*'*20) # for i in g: # print(i) =======結果======== 5 4 ==================== 3 2 1 ********************
yiled與return的區別:
x=2 y=3 # if x > y: # print(x) # else: # print(y) # res='aaaaa' if x > y else 'bbbbbbb' #三元表達式---->【 條件成立 條件 條件不成立】 # # print(res)
2.列表解析<不能加else,條件成立的狀況下放到左邊。>
# l=[1,31,73,84,57,22] # l_new=[] # for i in l: # if i > 50: # l_new.append(i) # print(l_new) #列表解析 # res=[i for i in l if i > 50] # print(res)
3.生成器表達式
#g=(i for i in range(100000000000000000000000000000)) #print (g) #print(next(g)) ##next(g) == g.__next__() #print(next(g)) ##next(g) == g.__next__()