Python入門篇-生成器函數
python
做者:尹正傑async
版權聲明:原創做品,謝絕轉載!不然將追究法律責任。ide
一.生成器概述函數
1>.生成器generatorspa
生成器指的是生成器對象,能夠由生成器表達式獲得,也能夠使用yield關鍵字獲得一個生成器函數,調用這個函數獲得一個生成器對象
2>. 生成器函數線程
函數體中包含yield語句的函數,返回生成器對象
生成器對象,是一個可迭代對象,是一個迭代器
生成器對象,是延遲計算,惰性求值的
包含yield語句的生成器函數生成生成器對象的時候,生成器函數的函數體不會當即執行
next(generator)會從函數的當前位置向後執行到以後碰到的第一個yield語句,會彈出值,並暫停函數執行
再次調用next函數,和上一條同樣的處理過程
沒有多餘的yield語句能被執行,繼續調用next函數,會拋出StopIteration異常
3>.編寫一個生成器函數樣例code
1 #!/usr/bin/env python 2 #_*_coding:utf-8_*_ 3 #@author :yinzhengjie 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/ 5 #EMAIL:y1053419035@qq.com 6 7 """ 8 關於生成器函數的相關說明: 9 10 在生成器函數中,使用多個yield語句,執行一次後會暫停執行,把yield表達式的值返回 11 12 再次執行會執行到下一個yield語句 13 14 return 語句依然能夠終止函數運行,但return語句返回值不能被捕獲到 15 16 return 會致使沒法繼續獲取下一個值,拋出StopIteration異常 17 18 若是函數沒有顯示的return語句,若是生成器函數執行到結尾,同樣會拋出StopIteration異常喲 19 20 """ 21 def gen(): 22 print('line 1') 23 yield 1 24 print('line 2') 25 yield 2 26 print('line 3') 27 return 3 28 29 next(gen()) 30 31 next(gen()) 32 33 g = gen() 34 35 print(next(g)) 36 print(next(g)) 37 38 # print(next(g)) #報錯:StopIteration: 3,由於已經沒有多餘的yield語句啦,上面已經被調用兩次了 39 40 print(next(g, 'End')) #若是沒有元素就給個缺省值 41 42 43 44 #以上代碼執行結果以下: 45 line 1 46 line 1 47 line 1 48 1 49 line 2 50 2 51 line 3 52 End
二.生成器應用協程
1>.無限循環對象
1 #!/usr/bin/env python 2 #_*_coding:utf-8_*_ 3 #@author :yinzhengjie 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/ 5 #EMAIL:y1053419035@qq.com 6 7 8 def counter(): 9 i = 0 10 while True: 11 i += 1 12 yield i 13 14 def inc(c): 15 return next(c) 16 17 c = counter() #這是一個生成器對象 18 19 print(inc(c)) 20 print(inc(c)) 21 22 23 24 #以上代碼輸出結果以下: 25 1 26 2
2>.計數器blog
1 #!/usr/bin/env python 2 #_*_coding:utf-8_*_ 3 #@author :yinzhengjie 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/ 5 #EMAIL:y1053419035@qq.com 6 7 def inc(): 8 def counter(): 9 i = 0 10 while True: 11 i += 1 12 yield i 13 c = counter() 14 return lambda : next(c) #這裏返回的是匿名函數 15 16 foo = inc() 17 print(foo()) 18 print(foo()) 19 20 21 22 #以上代碼輸出結果以下: 23 1 24 2
3>.處理遞歸問題
1 #!/usr/bin/env python 2 #_*_coding:utf-8_*_ 3 #@author :yinzhengjie 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/ 5 #EMAIL:y1053419035@qq.com 6 7 8 def fib(): 9 x = 0 10 y = 1 11 while True: 12 yield y 13 x, y = y, x+y 14 15 foo = fib() 16 17 for _ in range(5): 18 print(next(foo)) 19 20 for _ in range(100): 21 next(foo) 22 23 print(next(foo)) 24 25 26 #以上代碼輸出結果以下: 27 1 28 1 29 2 30 3 31 5 32 6356306993006846248183
#!/usr/bin/env python #_*_coding:utf-8_*_ #@author :yinzhengjie #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/ #EMAIL:y1053419035@qq.com pre = 0 cur = 1 print(pre,cur,end=" ") def fib(n,pre=0,cur=1): pre,cur = cur,pre + cur print(cur,end=" ") if n == 2: return fib(n-1,pre,cur) fib(106)
4>.協程(coroutine)
(1)生成器的高級用法 (2)比進程,線程輕量級 (3)是在用戶空間調度的一種實現 (4)Python3 asyncio就是協程實現,已經加入到標準庫 (5)Python3.5 使用async,await關鍵字直接原生支持協程 協程調度器實現思路: 有2個生成器A,B next(A)後,A執行到了yield語句暫停,而後去執行next(B),B執行到yield語句也暫停,而後再次調用next(A),再調用next(B),周而復始,就實現了調度的效果 能夠引入調度的策略來實現切換的方式 (6)協程就是一種非搶佔式調度
三.yield from
1 #!/usr/bin/env python 2 #_*_coding:utf-8_*_ 3 #@author :yinzhengjie 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/ 5 #EMAIL:y1053419035@qq.com 6 7 8 def inc(): 9 for x in range(1000): 10 yield x 11 12 foo = inc() 13 print(next(foo)) 14 print(next(foo)) 15 print(next(foo)) 16 17 print("*" * 20 + "我是分割符" +"*" * 20) 18 19 """ 20 以上代碼能夠使用yield from代碼改寫,等價於下的代碼: 21 """ 22 def inc(): 23 yield from range(1000) 24 25 bar = inc() 26 print(next(bar)) 27 print(next(bar)) 28 print(next(bar)) 29 30 31 32 #以上代碼輸出結果以下: 33 0 34 1 35 2 36 ********************我是分割符******************** 37 0 38 1 39 2
#!/usr/bin/env python #_*_coding:utf-8_*_ #@author :yinzhengjie #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/ #EMAIL:y1053419035@qq.com """ yield from是Python 3.3出現新的語法 yield from iterable 是 for item in iterable: yield item 形式的語法糖 """ #從可迭代對象中一個個拿元素 def counter(n): for x in range(n): yield x def inc(n): yield from counter(n) foo = inc(10) print(next(foo)) print(next(foo)) #以上代碼執行結果以下: 0 1