python3生成器函數,Python生成器函數
python有關生成器函數的問題
你使用except將生成器退出的事件攔截了。
創新互聯建站長期為1000多家客戶提供的網站建設服務,團隊從業經驗10年,關注不同地域、不同群體,并針對不同對象提供差異化的產品和服務;打造開放共贏平臺,與合作伙伴共同營造健康的互聯網生態環境。為建陽企業提供專業的成都網站建設、成都做網站,建陽網站改版等技術服務。擁有十余年豐富建站經驗和眾多成功案例,為您定制開發。
這將導致生成器無法釋放。
如果需要處理未知錯誤,應當將StopIteration錯誤單獨except并直接拋出:
def?myGenerator():
value?=?1
while?True:
try:
yield?value
value?+=?1
except?StopIteration:
raise?StopIteration
except:
value?=?1
gen?=?myGenerator()
print(next(gen))
print(next(gen))
python 生成器是函數嗎
對于程序而言,內存也是很重要的,因為程序中很多數據都是保存在內存中的,如果內存中存儲的數據過多,那么系統就會崩潰,這是人們不希望發生的。
可以采用生成器推導式來解決內存不足的問題。例如,利用生成器推導式創建一個生成器n,數據為1~33數字,可以寫成n = (i for i in range(1, 34))。這樣當程序需要一個數時,程序才生成數據,可以節省內存。然而生成器推導式太過簡單,只能用一行代碼的形式實現,如果要創建復雜的生成器,如創建一個生成器f,生成前10個斐波那契數字,生成器推導式已經不能滿足需求了,因為斐波那契數列最開始的兩個數都無法賦值。
函數可以實現復雜的功能,然而要節省內存,就需要使用生成器函數。生成器函數與普通函數的區別是函數中包含關鍵字yield。實際上只要含有yield關鍵字的函數就是生成器函數。
生成器函數是用函數實現生成器。定義生成器函數的語法格式如下:
def?fib():???#?定義生成器函數
...?????a,?b?=?1,?1???#?定義初始值
...?????while?True:
...?????????yield?a???#?暫停執行,返回一個新變量值
...?????????a,?b?=?b,?a+b
...
a=?fib()???#?調用生成器函數
for?i?in?range(10):
...?????print(next(a))???#?調用生成器函數的yield生成值
...
1
1
2
3
5
8
13
21
34
55
def 函數名(參數):
函數體
yield 變量名
函數體
由語法格式可知,生成器函數與普通函數的區別在于函數體部分,生成器函數的函數體含有“yield 變量名”語句。yield的功能類似于return,return是函數返回值,yield的功能也是返回變量,但是它僅返回變量而不退出函數,因此,yield可以看作是多次返回變量且不會退出函數的return。
在調用生成器函數時,寫上函數名與參數,并通過一個變量接收返回值,語法格式如下:
變量名 = 函數名(參數)
調用生成器函數的yield生成值的第一種方法如下:
next(變量名)
第二種方法如下:
變量名.__next__()
在掌握了生成器函數的定義和調用之后,就可以使用生成器函數實現生成前10個斐波那契數字的案例了。這個案例主要分為三步,第一步是定義生成器函數,第二步是調用并賦值,第三步是打印結果,代碼如下:
在上述程序中,首先定義生成器函數fib(),函數內先定義斐波那契數列的兩個初始值,再寫一個while True死循環。這個死循環有些特別,先是用yield生成待使用的數字,再通過賦值語句“a, b = b, a+b”將b的值賦給a,將a+b的值賦給b,每次循環都是如此。然后調用生成器函數fib(),再調用生成器函數的yield生成值,最后打印結果。由于需要生成前10個斐波那契數字,因此可以采用for循環,每循環一次生成并打印一個斐波那契數字,共循環10次。第一次循環時,調用yield生成值a,即1;第二次循環時,調用yield生成值a,a被賦值成b的值,即1,而b被賦值成a+b的值,即2;第三次循環時,調用yield生成值a,a被賦值成b的值,而此時b的值是上次賦值的a+b的值,即2……以此類推,就得到了整個斐波那契數列。
Python創建生成器的兩種方法
創建生成器方法
方法一?
要創建一個生成器,有很多種方法。第一種方法很簡單,只要把一個列表生成式的[ ]改成( )
創建L和G的區別僅在于最外層的[ ]和( ),L是一個列表,而G是一個生成器。我們可以直接打印出L的每一個元素,但我們怎么打印出G的每一個元素呢?如果要一個一個打印出來,可以通過next()函數獲得生成器的下一個返回值:
運行結果:
運行結果:
生成器保存的是算法,每次調用next(G),就計算出G的下一個元素的值,直到計算到最后一個元素,沒有更多的元素時,拋出StopIteration的異常。當然,這種不斷調用next()實在是太變態了,正確的方法是使用for循環,因為生成器也是可迭代對象。所以,我們創建了一個生成器后,基本上永遠不會調用next(),而是通過for循環來迭代它,并且不需要關心StopIteration異常。
相關推薦:《Python視頻教程》
方法2?
generator非常強大。如果推算的算法比較復雜,用類似列表生成式的for循環無法實現的時候,還可以用函數來實現。
比如,著名的斐波拉契數列(Fibonacci),除第一個和第二個數外,任意一個數都可由前兩個數相加得到:
1, 1, 2, 3, 5, 8, 13, 21, 34, ...
斐波拉契數列用列表生成式寫不出來,但是,用函數把它打印出來卻很容易:
運行結果:
仔細觀察,可以看出,fib函數實際上是定義了斐波拉契數列的推算規則,可以從第一個元素開始,推算出后續任意的元素,這種邏輯其實非常類似generator。
也就是說,上面的函數和generator僅一步之遙。要把fib函數變成generator,只需要把print(b)改為yield b就可以了:
運行結果:
在上面fib的例子,我們在循環過程中不斷調用yield,就會不斷中斷。當然要給循環設置一個條件來退出循環,不然就會產生一個無限數列出來。同樣的,把函數改成generator后,我們基本上從來不會用next()來獲取下一個返回值,而是直接使用for循環來迭代:
運行結果:
但是用for循環調用generator時,發現拿不到generator的return語句的返回值。如果想要拿到返回值,必須捕獲StopIteration錯誤,返回值包含在StopIteration的value中:
運行結果:
相關推薦:
三分鐘看懂什么是Python生成器
網站欄目:python3生成器函數,Python生成器函數
標題路徑:http://www.xueling.net.cn/article/dssgccs.html