Python小白學習之路(二十三)—【生成器補充】
阿新 • • 發佈:2018-12-06
生成器的一些補充
接著下雞蛋和吃包子!
補充一:生成器只能遍歷一次
(總是把生成器比喻成母雞下雞蛋,需要一個下一個,首先是下出來的雞蛋不能塞回
母雞肚子裡,其次是一個母雞一生只能下一定數量的雞蛋,下完了就死掉了)
#通過程式來理解什麼意思 #程式一: def test(): for i in range(2): yield i t = test() for i in t: print(i) t1 =(i for i in t) print(list(t1)) #執行結果 0 1 []
#程式分析 #1.程式開始執行以後,因為test函式中有yield關鍵字,所以test函式並不會真的執行,而是先得到一個生成器t.#2.for迴圈遍歷生成器t,並列印遍歷結果0和1 #3.繼續利用for迴圈遍歷生成器t,因為該生成器已經遍歷過一次,所有值已經取完,所以這次遍歷不會取到任何值,則列印遍歷結果為空列表
#程式二:
#實現功能:人口普查,
#功能一:統計 “人口統計” 檔案中所有省份的總人數
#功能二:並計算出每一省份人數佔總人數的百分比
#人口普查.text檔案內容 {'name': '北京', 'population': 100} {'name': '天津', 'population': 999} {'name': '南京', 'population': 750} {'name': '上海', 'population': 870} #程式: def get_population(): with open('人口普查', 'r', encoding = 'utf-8') as f: for i in f: yield i g = get_population() all_population=sum(eval(i)['population'] for i in g) print(all_population) for i in g: single_population = eval(i)['population']print( single_population / all_population)
#程式分析: #1.程式開始執行以後,因為get_population函式中有yield關鍵字,所以get_population函式並不會真的執行,而是先得到一個生成器g. #2.all_population=sum(eval(i)['population'] for i in g) 總人數的獲取 #對這段程式碼進行翻譯一下 #第一步:通過for迴圈進行遍歷生成器 g,其實就是執行 get_population 函式,開啟txet檔案,讀取每一行內容 #第二步:每一行的內容讀出來為字串型別,通過eval()將字串轉換成字典型別,通過索引進行對每個省人口進行取值 #第三步:通過sum函式,對所取的值進行求和,計算總人口數 #3.通過對生成器g進行遍歷,取出每一個省份的人數,並列印百分比
#通過分析,上述程式可實現要求。可執行結果如下: 2719
#只計算出總人數。為什麼沒有執行第二次遍歷?原因就在於計算總人口時已經對生成器g遍歷了一次,將值全部取出第二次遍歷時,生成器中並沒有值,因此也不會取出每一個省份的人數,並列印百分比
#程式改進(遍歷時儲存取值即可) def get_population(): with open('人口普查', 'r', encoding = 'utf-8') as f: for i in f: yield i g = get_population() s1 = eval(g.__next__())['population'] s2 = eval(g.__next__())['population'] s3 = eval(g.__next__())['population'] s4 = eval(g.__next__())['population'] s = [s1, s2 , s3, s4] all_population = s1 + s2 + s3 + s4 for i in range(4): print(s[i] / all_population) #執行結果 2719 0.036778227289444645 0.367414490621552 0.2758367046708349 0.3199705774181684
雖然功能實現了,可是我認為自己的程式寫的實在太蹩腳了
因為沒有什麼基礎,所以只能按照功能區一步一步寫
希望之後有是有改進吧
大家對這個程式的實現有什麼好的想法可以和我交流一下
補充二:生產消費者模型(本質是對 yield 一個應用)
#以吃包子的列子
#我們去包子鋪買包子,肯定是去了店家邊做邊賣包子
#店家肯定不會讓所有人等著,把需要的所有包子都做好,再賣給大家
#最高效率的就是我做一個人的,賣一個人的量
#現做現賣
#我們用程式來模擬這個過程
#吃包子進化理論(我自己胡亂起的名字)
#程式一:(只能實現一個人吃了一個包子) def producer_bun(): c1 = consumer('xhg') c1.__next__() c1.send('豬肉餡兒') def consumer(name): print('我是%s,我準備開始吃包子了'%name) while True: bun = yield print('%s很開心的把%s吃掉了'%(name, bun)) producer_bun() #執行結果 我是xhg,我準備開始吃包子了 xhg很開心的把豬肉餡兒吃掉了
#程式二:(只能實現一個人吃了多個包子) def producer_bun(): c1 = consumer('xhg') c1.__next__() for i in range(3): c1.send('包子%s'%i) def consumer(name): print('我是%s,我準備開始吃包子了'%name) while True: bun = yield print('%s很開心的把%s吃掉了'%(name, bun)) producer_bun() #執行結果 我是xhg,我準備開始吃包子了 xhg很開心的把包子0吃掉了 xhg很開心的把包子1吃掉了 xhg很開心的把包子2吃掉了
#最終版完美吃包子程式 def producer_bun(): c1 = consumer('xhg1') c2 = consumer('xhg2') c1.__next__() c2.__next__() for i in range(3): c1.send('包子%s'%i) c2.send('包子%s' % i) def consumer(name): print('我是%s,我準備開始吃包子了'%name) while True: bun = yield print('%s很開心的把%s吃掉了'%(name, bun)) producer_bun()
設定斷點,可以清楚的幫我們分析程式的執行過程。以此來充分理解yield的作用。
數字代表程式執行步驟
通過yield實現兩個函式之間的切換
其中send函式作用同next函式
send()的兩個功能:1.傳值;2.next()。