十一、叠代器、生成器
叠代
叠代是一個重復的過程,每次重復即一次叠代,並且每次叠代的結果都是基於下一次叠代的結果
如公司軟件:基於第一次基礎上修改,發第二個版本,基於第二個,發第三個。。。
循環 while True: name = input(‘名字:‘) print(name) 叠代 count = 0 while count<10: print(count) count+=1
可叠代對象:
python提供的不依賴索引的叠代方式,會為一些對象內置 __iter__ 方法
只要有 __iter__ 方法的對象,就是可叠代對象
可叠代對象有:
字符串 列表 元組 字典 集合 文件對象
對象執行 __iter__ 方法後,得到的就是叠代器
叠代器
既有 __iter__ 方法,又有 __next__ 方法
__next__方法不依賴索引叠代對象,__next__一次叠代一次
當叠代超出,會提示 StopIteration,沒有這個值
d = {‘a‘:1,‘b‘:2,‘c‘:3,‘d‘:4} i = d.__iter__() # 得到叠代器 i print(i.__next__()) print(i.__next__()) print(i.__next__()) print(i.__next__()) print(i.__next__()) # StopIteration
優點:
1.不依賴索引(統一了叠代方式)
2.節省內存,惰性計算,同一時間內存只有一個值 (比如讀文件內容,不一下全讀出來,節省內存)
缺點:
1.只能一次性往後next取值
2.無法獲取長度
for循環與叠代器:
之前說過字典沒有索引,直接通過 for i in dict 可以取值
原理就是:
i = d.__iter__() i.__next() 被循環的對象執行__iter__方法到的 i i 自動執行__next__ 直到報出StopIteration結束,for循環捕捉處理
所以 for 可以直接循環叠代器:
def func(): print(1) yield 1 print(2) yield None print(3) yield #這裏不加yield,報StopIteration g = func().__iter__() for i in g: print(i) # 1 None None
生成器
生成器函數
函數體包含 yield 關鍵字,這個函數執行的結果就是生成器
yeild 將函數做成了生成器,遵循叠代器的取值方式
def func(): print(‘真‘) yield print(‘帥‘) g = func() print(g) # <generator object func at 0x00000214686B6990>
生成器也具有 __iter__ 和 __next__ 方法,實際生成器就是叠代器:
l = [1,2,3,4,5] b = l.__iter__() print(b.__next__()) # 觸發一次叠代列表操作,取一次值就結束 def func(): print(‘真‘) yield print(‘帥‘) g = func() g.__next__() # 觸發一次函數的執行,函數的結束標準是 return 這裏的 yield 就相當於 return 的終止執行操作 def func(): print(1) yield 1 print(2) yield None print(3) yield #這裏不加yield,報StopIteration g = func() g.__next__() g.__next__() g.__next__() # 碰到yield 就暫停,返回值,然後再執行next,函數繼續從暫停位置執行,依次類推; # 如果函數執行最後沒有返回值,就報StopIteration # 與 return 的區別: 1.可以返回多次值,return只能1次 # 2.保存執行狀態,繼續向下執行,return執行就終止函數
模擬linux中 tail -f 命令(動態查看文件新增的一行內容):
分析:
1.一次讀一行:readline
2.最新一行:光標要在每行的最後位置
3.循環上兩步操作
4.讀到內容返回,沒讀到重新進入循環
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=‘‘) else: time.sleep(1) tail(‘a.txt‘)
增加過濾 tail - f a.txt | grep ‘shuai‘ 過濾出 shuai
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: yield line else: time.sleep(1) # g = tail(‘a.txt‘) def grep(lines,item): for line in lines: if item in line: yield line grep_g = (tail(‘a.txt‘),‘shuai‘)
for i in grep_g:
print(i)
| 管道符:左邊的執行結果返回給右邊
再來個
def foo(n): while n>0: yield n n-=1 g = foo(6) print(g.__next__()) # 6 print(g.__next__()) # 5 for i in g: print(i) # 4 3 2 1 叠代器是一次性的,只能一直往後取,for把剩下的值取了 def foo(n): while n>0: yield n n-=1 g = foo(6) for i in foo(6): print(i) # 6 5 4 3 2 1 for i in foo(6): print(i) # 6 5 4 3 2 1 這裏的兩個for 是循環單獨的生成器 def foo(n): while n>0: yield n n-=1 print(foo(6).__next__()) # 6 print(foo(6).__next__()) # 6 這兩次也是操作了兩個生成器
十一、叠代器、生成器