您好,登錄后才能下訂單哦!
這篇文章給大家介紹怎么分析Python生成器、迭代器與yield語句,內容非常詳細,感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。
今天要分享的內容是Python的生成器、迭代器與yield語句。主要包括什么是生成器,如何定義一個生成器,如何調用生成器包含的元素。迭代器也是一樣的,最后介紹yield語句,以及它和生成器有什么關系。
[* ! *] 理解本文需要一定的基礎,需要了解Python列表的定義,基本操作,字典,元組,字符串的概念。Python中for循環的語法結構,以及需要知道
if __name__ =="__main__":
的作用是什么?
1. 迭代
首先來看一下迭代的定義:
如果給定一個列表list或元組tuple,我們可以通過for循環來遍歷這個list或tuple,這種遍歷我們稱為迭代(Iteration)。
用人話說一遍就是給一個列表或者元組,把里面的元素挨個看看都是啥,且只看一遍,就叫做迭代。下面寫個簡單的栗子。首先定義一個list_a,然后通過for循環遍歷每一個元素,并打印出list_a中的每一個元素(圖1),這就是對list_a迭代的過程。
迭代器的定義:
可以被next()函數調用并不斷返回下一個值的對象稱為迭代器(Iterator)。
一般來說迭代器都是可以迭代的。
圖1
剛才介紹的是對Python中列表的迭代,那么對于其他對象是不是也可以迭代呢?怎么來判斷一個對象是不是可迭代的呢?我們可以利用collections模塊中的Iterable函數來判斷一個對象是不是可迭代的。比如:
分別定義列表,元組,字符串,字典,整數5種數據類型a,b,c,d,e,然后分別判斷是否可迭代,見圖2。結果可以看到除了整數不可迭代外,其他4種數據類型都是可迭代的。
圖2
2. 列表生成式
顧名思義,列表生成式就是用來自動創建一個列表表達式。使用列表生成式來創建列表的一個好處是可以簡化代碼,使代碼美觀,減少工作量。
舉個簡單的栗子,我們定義一個列表,name_list,然后利用列表生成式,將name_list中的大寫字母全部變為小寫字母。其中
[name.lower() for name in name_list]
就是列表生成式,首先定義對象的某種運算,然后定義一個for循環來遍歷對象。
圖3
3. 生成器
列表生成式一般用于列表不是特別長,占用內存比較小的情況,如果數據量很大,生成器是比列表生成式更好的選擇。在Python中,一邊進行某種運算,一遍進行循環的機制稱為生成器(Generator)。定義一個生成器有一種很簡單的方法,就是把列表生成式中的[ ]改為( )即可。還是剛才的栗子,我們把生成器對象打印一下,看到
<generator object <genexpr> at 0x00000000038FF828>
lower_name_list是一個generator object,生成器對象。
圖4
然后介紹一下怎么查看這個生成器對象中有哪些元素?對于生成器對象來說,使用生成器的next()方法來輸出每一個對象。Next()的意思就是下一個,就好像是next()對生成器說,來吧,下一個,生成器就把下一個元素吐出來了,知道生成器中沒有可迭代的對象的時候,就會拋出StopIteration異常(圖5)。
圖5
接下來我們學習另外一種輸出生成器中元素的方法,就是用for循環來迭代生成器中的元素(圖6)。這是因為生成器是一種可迭代的對象,所以可以使用for循環來遍歷。
>>> isinstance(lower_name_list1,Iterable)
>>> True
圖6
4. yield語句
接下來就到了我們今天的重點要介紹的東西,這里必須強行安利一波,yield很有用很有用,最好能熟練掌握。然后為什么這么說呢?這個我要扯一會兒深度學習,我們說的機器學習,或者深度學習,其中非常重要的一個環節就是讀取數據,就是把數據讀進來然后交給我們的模型去訓練,去學習。那么問題來了,給你一個100萬張圖片,或者1G的文本數據,你怎么來讀數據?傳統的方法在求解機器學習算法的時候,大部分是使用批梯度下降法(Batch Gradient Descent),一般是一次性把數據都讀進來,然后整體做梯度下降。但是現在是大數據時代了,數據量一般都很大,如果一次讀進來,內存肯定不夠用,如果是GPU,同樣顯存也不夠用。所以就有了后來的mini-batch 梯度下降,到底有多mini呢,通常遠遠小于全部數據量,這個數字就是我們在訓練模型的時候取得batchsize的大小。意思就是從一個很大的數據集里面,每次只取很小的一部分數據集,然后遍歷整個數據集。
這個思想和Python的yield語句極為吻合,所以我強烈推薦大家掌握yield語句。下面我們開始yield語句的學習。
首先來看一下Python官方文檔中,對yield的解釋。
意思是:yiled語句僅在定義一個生成器函數的時候使用,并且在生成器函數的函數體里面使用。在函數定義中使用yield語句之后,這個函數就不是一般的函數,而是生成器函數。
當我們調用生成器函數的時候,將會返回一個生成器。我們通過調用生成器的next()方法來執行生成器函數,直到拋出異常。
當執行yield語句的時候,生成器對象是被凍結的,執行的結果只有next()方法所返回的list。凍結的意思是除了next()方法可以返回一個列表以外,其他的變量都不會執行。
把這段文檔簡單理解一下就是我們可以通過定義一個包含yield語句的函數,來定義一個生成器函數。這個生成器函數可以通過next()方法來執行。
下面我們舉個具體的栗子,來看一下yield的執行原理。
首先我們定義了兩個函數,yield_test()和yield_test2(),第一個函數是用return來返回輸出值,第二個函數用yield來返回。這樣做是為了反映return和yield的區別,也是為了體現包含yield語句函數的不同之處。為什么要做這個比較呢,說白了,yield語句其實也是返回一個值,只不過這個返回方式不太尋常,它是以生成器函數的形式返回,所以我們對比一下和return的區別,看看哪里不一樣。
# - * -coding:utf-8 - * -
defyield_test():
list_a = range(5)
list_b = []
for i in list_a:
list_b.append(i * i)
return list_b
defyield_test2():
list_a = range(5)
for i in list_a:
yield i * i
if __name__ =="__main__":
results = yield_test()
results2 = yield_test2()
print("The results is:", results)
print("The type of results is: ",type(results))
print("The results2 is: ",results2)
print("The type of results2 is:", type(results2))
result_list = []
for x in results2:
result_list.append(x)
print("The result_list is:",result_list)
下面是程序輸出結果
"""
('The results is:', [0, 1, 4, 9, 16])
('The type of results is: ', <type 'list'>)
('The results2is: ', <generator object yield_test2 at 0x00000000040F6630>)
('The type of results2 is: ', <type 'generator'>)
('The result_list is:', [0, 1, 4, 9, 16])
"""
關于怎么分析Python生成器、迭代器與yield語句就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。