day 14 - 1 生成器
阿新 • • 發佈:2018-12-09
生成器
生成器
生成器的本質就是迭代器
生成器的表現形式
生成器函式
生成器函式 —— 本質上就是我們自己寫得函式
生成器表示式
生成器函式:
含有 yield 關鍵字的函式就是生成器函式
特點:
呼叫函式的之後函式不執行,返回一個生成器
每次呼叫 next 方法的時候會取到一個值
直到取完最後一個,在執行 next 會報錯
從生成器中取值的幾個方法
1、next
2、for
3、資料型別的強制轉換:佔用記憶體 print(list(g))
生成器函式
我們先來看下普通函式
def generator(): print(1)return 'a' ret = generator() print(ret)
接著來看生成器函式
#只要含有yield關鍵字的函式都是生成器函式 # yield 不能和 return 共用且需要寫在函式內 def generator(): print(1) yield 'a' #生成器函式:在執行之後會得到一個生成器作為返回值 ret = generator() #此處的 ret 是一個生成器而不是值了 print(ret) #此處在同過原來的呼叫方法呼叫的是記憶體地址 print(ret.__next__()) #通過 .__next__() 來呼叫函式的輸出內容
下面來看一個生成器函式的例子
#在取值時 會取到第一個 yield 時停止,然後等待下一次取值的動作開始,繼續取值到下一個 yield def generator(): print(1) yield 'a' print(2) yield 'b' print(3) yield 'c' g = generator() ret = g.__next__() #單獨執行第一次時:1 a print(ret) ret = g.__next__() #即:可以控制執行的位置 print(ret) ret = g.__next__() print(ret) for i in g: #使用 for 迴圈也同樣可以 print(i) #但 for 迴圈不可以控制執行位置
寫一個函式 製造 200w 個娃哈哈
ef wahaha(*args): for i in range(2000000): yield "娃哈哈%s"%i ret = wahaha(1000) #呼叫 #for i in ret: # print(i) #呼叫前 50 個 count=0 for i in ret: print(i) count+=1 if count > 50: break print(ret.__next__()) #這裡一起執行會接著 for 迴圈呼叫 ret ,返回第 51個
監聽檔案輸入的例子
#當檢查到檔案中有輸入含有 python 字元時就會在螢幕上列印 def tail(filename): f = open(filename,encoding='utf-8') #檔案控制代碼 while True: line = f.readline() if line.strip(): yield line.strip() ret = tail('D:/py/log/test.txt') for i in ret: if 'python' in i: print('***',i)
生成器函式進階
關鍵字 send 的使用
#send 獲取下一個值的效果和 next 基本一致 #只是在獲取下一個值的時候,給上一 yield 的位置傳遞一個數據 #使用 send 的注意事項 # 第一次使用生成器的時候 要、必須用 next 獲取下一個值 # 最後一個 yield 不能接受外部的值 def generator(): print(123) content = yield 1 print('=====',content) print(456) yield 2 g = generator() ret = g.__next__() print('***',ret) ret = g.send('hello') #向函式 content 的位置傳值 print('***',ret)
獲取移動平均值(每次輸入一個值都會計算出一個平均值)
10 20 30 10
10 15 20 17.5
avg = sum/count
def average(): sum = 0 count = 0 avg = 0 while True: num = yield avg sum +=num count += 1 avg = sum/count avg = average() avgs = avg.__next__() avgs = avg.send(10) avgs = avg.send(30) avgs = avg.send(60) avgs = avg.send(60) print(avgs)
預激生成器的裝飾器
獲取移動平均值進階與裝飾器的使用
#裝飾器的作用就是在使用者使用時,少寫一句 ret = g.__next__() 方便操作 def init(func): def inner(*args,**kwargs): ret = func(*args,**kwargs) ret.__next__() return ret return inner @init def average(): sum =0 count = 0 avg = 0 while True: num = yield avg sum += num count += 1 avg=sum/count avg = average() ret = avg.send(10) ret = avg.send(20) ret = avg.send(60) print(ret) ret = avg.send(20) ret = avg.send(20) print(ret)
from 關鍵字的使用
#先來看一個 for 迴圈的例子,取出字串中所有的單個字元 def generator(): a = 'abcde' b = '12345' for i in a: yield i for i in b: yield i g = generator() for i in g: print(i) #使用 from 關鍵字取出 def generator(): a = 'abcde' b = '12345' yield from a yield from b g = generator() for i in g: print(i)
生成器的表示式