1. 程式人生 > >Python小白學習之路(二十三)—【生成器補充】

Python小白學習之路(二十三)—【生成器補充】

生成器的一些補充

接著下雞蛋和吃包子!

 

補充一:生成器只能遍歷一次


(總是把生成器比喻成母雞下雞蛋,需要一個下一個,首先是下出來的雞蛋不能塞回
母雞肚子裡,其次是一個母雞一生只能下一定數量的雞蛋,下完了就死掉了)

#通過程式來理解什麼意思
#程式一:

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()。