迭代器 迭代就是重覆的一個過程,但是不是單純的重覆,每一次的重覆都是基於上一次的結果產生的。不過只記住迭代他就是重覆的執行過程就是了。 迭代器就是迭代取數的一個工具,關鍵是我們為什麼要用迭代器呢?我們都知道python中主要的一些數據類型有整型,字元串,元祖,列表,字典,集合,文件等。對於整型而言只 ...
迭代器
迭代就是重覆的一個過程,但是不是單純的重覆,每一次的重覆都是基於上一次的結果產生的。不過只記住迭代他就是重覆的執行過程就是了。
#單純的重覆不是迭代,例如: count = 0 while count < 3: print(count) count += 1 #每一次的重覆都是基於上一次的結果產生的,隨著count的改變輸出不同的結果 count = 0 list = ["a", "b", "c"] while count < 3: print(list[count]) count += 1
迭代器就是迭代取數的一個工具,關鍵是我們為什麼要用迭代器呢?我們都知道python中主要的一些數據類型有整型,字元串,元祖,列表,字典,集合,文件等。對於整型而言只要一個數沒有什麼迭代器的概念,對於字元串,元祖和列表我們可以通過索引去取值,但是對於字典,集合以及文件而言,我們怎麼去像列表一樣進行取值呢?這就是迭代器引入的原因,主要就是為了不依賴與索引進行迭代取值。在python中兩個概念,一個就是可迭代對象(只要有__iter__方法的我們就稱之為可迭代對象,字元串,元祖,列表,字典,集合都是可迭代對象),二是迭代器對象(不僅要有__iter__方法而且還要有__next__方法,文件是迭代器對象),從上面的描述我們就可以看出來,迭代器對象都是可迭代的對象,但是可迭代對象卻不一定是迭代器對象。
迭代器的使用方法
dic = {'name': 'hu', 'age': 12} iter_dic = dic.__iter__() # 可迭代對象要變成迭代器才能夠進行使用 res = iter_dic.__next__() # 變成迭代器之後通過__next__方法進行迭代取值 print(res) # 對於dic迭代的值是key
當迭代器把迭代對象迴圈完畢之後會報錯
dic = {'name': 'hu', 'age': 12} count = 0 iter_dic = dic.__iter__() # 可迭代對象要變成迭代器才能夠進行使用 while count < len(dic): try: # 當最後一個迭代完了之後會報錯,因此我們需要捕捉異常 res = iter_dic.__next__() # 變成迭代器之後通過__next__方法進行迭代取值 print(res) # 對於dic迭代的值是key except StopIteration: break
從上面的代碼我們就可以看出來,對於迭代器的使用太過於麻煩,因此python給我們專門的設計了一個迴圈for迴圈來解決這樣的事情,for迴圈可以專門的去解決可迭代對象的問題,當然迭代器對象的問題也可以,for迴圈處理的步驟1. 把可迭代對象轉換成迭代器,(迭代器的話也會執行__iter__的方法,效果是一樣的)2. 迴圈的去調用__next__方法進行迭代取值。3. 通過try去捕捉異常,捕捉到異常之後停止迴圈。
# 和上面的代碼顯示的效果是一樣的 dic = {'name': 'hu', 'age': 12} for i in dic: print(i)
生成器
生成器本質上就是迭代器,只不過這個生成器是我們自己通過yield關鍵字自己創建的迭代器而已。迭代器有兩個優點 1. 可以不依賴與索引迭代取值 2.節省記憶體。而我們創建生成器為瞭解決最大的問題其實就是節省記憶體。
生成器創建的規則, 通過yield關鍵字進行創建迭代器。yield和return返回的是一樣的,只是yield可以中斷函數,當我需要的時候可以重新再進行創建
def foo() print(1) yield "第一" print(2) yield "第二" iter_foo = foo() print(iter_foo) next(iter_foo)
三元表達式
def max2(a, b): if a > b: return a else: return b a = 1 b = 2 c = a if a > b else b # 這一行數據就是上面那一個函數的簡潔的表達方式 print(c) c = max2(a, b) print(c)
列表生成式
l = [] for i in range(10): if i > 5: s = "egg%s" % i l.append(s) print(l) l = ["egg%s" % i for i in range(10) if i > 5] # 這一句話和前面的幾句話都是性質是一樣的,只是簡寫了而已 print(l)
生成字典表達式
d = {} s = [("hu", 12), ("zhou", 14)] for k, v in s: d[k] = v print(d) d = {k : v for k, v in s} # 這個是上面幾行代碼的縮寫 print(d)
生成器表達式
res = (i ** 2 for i in range(5)) print(res) print(next(res)) print(next(res)) print(next(res))
練習題:
1. 編寫一個range的生成器
![](http://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
def my_range(start, end , step=1): while start < end: yield start start += step for i in my_range(0, 10): print(i)View Code
2. 求一個文件中所包含的字元的個數,以及左右行中最大的個數
![](http://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
with open(r'04_多層裝飾器的聯繫.py', 'rt', encoding='utf-8') as f: # count = 0 # for line in f: # count += 1 # data = f.read() # print(len(data)) 649 # count = 0 # for line in f: # count += len(line) # print(count) # print(sum(len(line) for line in f)) print(max(len(line) for line in f)) # 通過生成器表達式一行寫出View Code
3. 模擬管道,實現功能:tail -f access.log | grep '404'
![](http://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# 2、模擬管道,實現功能:tail -f access.log | grep '404' import time def tail(file_path): with open(file_path, 'rb') as f: f.seek(0, 2) while True: # 查看是否有新的一行加入 line = f.readline() if line: yield line else: time.sleep(0.2) def grep(pattern, iter_tail): for line in iter_tail: line = line.decode('utf-8') if pattern in line: yield line for line in grep('404', tail('access.log')): print(line)View Code