這篇文章給大家介紹怎么分析Python生成器、迭代器與yield語句,內(nèi)容非常詳細,感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。
創(chuàng)新互聯(lián)建站秉承實現(xiàn)全網(wǎng)價值營銷的理念,以專業(yè)定制企業(yè)官網(wǎng),成都網(wǎng)站建設、網(wǎng)站建設,微信小程序,網(wǎng)頁設計制作,移動網(wǎng)站建設,成都營銷網(wǎng)站建設幫助傳統(tǒng)企業(yè)實現(xiàn)“互聯(lián)網(wǎng)+”轉型升級專業(yè)定制企業(yè)官網(wǎng),公司注重人才、技術和管理,匯聚了一批優(yōu)秀的互聯(lián)網(wǎng)技術人才,對客戶都以感恩的心態(tài)奉獻自己的專業(yè)和所長。
今天要分享的內(nèi)容是Python的生成器、迭代器與yield語句。主要包括什么是生成器,如何定義一個生成器,如何調用生成器包含的元素。迭代器也是一樣的,最后介紹yield語句,以及它和生成器有什么關系。
[* ! *] 理解本文需要一定的基礎,需要了解Python列表的定義,基本操作,字典,元組,字符串的概念。Python中for循環(huán)的語法結構,以及需要知道
if __name__ =="__main__":
的作用是什么?
1. 迭代
首先來看一下迭代的定義:
如果給定一個列表list或元組tuple,我們可以通過for循環(huán)來遍歷這個list或tuple,這種遍歷我們稱為迭代(Iteration)。
用人話說一遍就是給一個列表或者元組,把里面的元素挨個看看都是啥,且只看一遍,就叫做迭代。下面寫個簡單的栗子。首先定義一個list_a,然后通過for循環(huán)遍歷每一個元素,并打印出list_a中的每一個元素(圖1),這就是對list_a迭代的過程。
迭代器的定義:
可以被next()函數(shù)調用并不斷返回下一個值的對象稱為迭代器(Iterator)。
一般來說迭代器都是可以迭代的。
圖1
剛才介紹的是對Python中列表的迭代,那么對于其他對象是不是也可以迭代呢?怎么來判斷一個對象是不是可迭代的呢?我們可以利用collections模塊中的Iterable函數(shù)來判斷一個對象是不是可迭代的。比如:
分別定義列表,元組,字符串,字典,整數(shù)5種數(shù)據(jù)類型a,b,c,d,e,然后分別判斷是否可迭代,見圖2。結果可以看到除了整數(shù)不可迭代外,其他4種數(shù)據(jù)類型都是可迭代的。
圖2
2. 列表生成式
顧名思義,列表生成式就是用來自動創(chuàng)建一個列表表達式。使用列表生成式來創(chuàng)建列表的一個好處是可以簡化代碼,使代碼美觀,減少工作量。
舉個簡單的栗子,我們定義一個列表,name_list,然后利用列表生成式,將name_list中的大寫字母全部變?yōu)樾懽帜浮F渲?/p>
[name.lower() for name in name_list]
就是列表生成式,首先定義對象的某種運算,然后定義一個for循環(huán)來遍歷對象。
圖3
3. 生成器
列表生成式一般用于列表不是特別長,占用內(nèi)存比較小的情況,如果數(shù)據(jù)量很大,生成器是比列表生成式更好的選擇。在Python中,一邊進行某種運算,一遍進行循環(huán)的機制稱為生成器(Generator)。定義一個生成器有一種很簡單的方法,就是把列表生成式中的[ ]改為( )即可。還是剛才的栗子,我們把生成器對象打印一下,看到
lower_name_list是一個generator object,生成器對象。
圖4
然后介紹一下怎么查看這個生成器對象中有哪些元素?對于生成器對象來說,使用生成器的next()方法來輸出每一個對象。Next()的意思就是下一個,就好像是next()對生成器說,來吧,下一個,生成器就把下一個元素吐出來了,知道生成器中沒有可迭代的對象的時候,就會拋出StopIteration異常(圖5)。
圖5
接下來我們學習另外一種輸出生成器中元素的方法,就是用for循環(huán)來迭代生成器中的元素(圖6)。這是因為生成器是一種可迭代的對象,所以可以使用for循環(huán)來遍歷。
>>> isinstance(lower_name_list1,Iterable)
>>> True
圖6
4. yield語句
接下來就到了我們今天的重點要介紹的東西,這里必須強行安利一波,yield很有用很有用,最好能熟練掌握。然后為什么這么說呢?這個我要扯一會兒深度學習,我們說的機器學習,或者深度學習,其中非常重要的一個環(huán)節(jié)就是讀取數(shù)據(jù),就是把數(shù)據(jù)讀進來然后交給我們的模型去訓練,去學習。那么問題來了,給你一個100萬張圖片,或者1G的文本數(shù)據(jù),你怎么來讀數(shù)據(jù)?傳統(tǒng)的方法在求解機器學習算法的時候,大部分是使用批梯度下降法(Batch Gradient Descent),一般是一次性把數(shù)據(jù)都讀進來,然后整體做梯度下降。但是現(xiàn)在是大數(shù)據(jù)時代了,數(shù)據(jù)量一般都很大,如果一次讀進來,內(nèi)存肯定不夠用,如果是GPU,同樣顯存也不夠用。所以就有了后來的mini-batch 梯度下降,到底有多mini呢,通常遠遠小于全部數(shù)據(jù)量,這個數(shù)字就是我們在訓練模型的時候取得batchsize的大小。意思就是從一個很大的數(shù)據(jù)集里面,每次只取很小的一部分數(shù)據(jù)集,然后遍歷整個數(shù)據(jù)集。
這個思想和Python的yield語句極為吻合,所以我強烈推薦大家掌握yield語句。下面我們開始yield語句的學習。
首先來看一下Python官方文檔中,對yield的解釋。
意思是:yiled語句僅在定義一個生成器函數(shù)的時候使用,并且在生成器函數(shù)的函數(shù)體里面使用。在函數(shù)定義中使用yield語句之后,這個函數(shù)就不是一般的函數(shù),而是生成器函數(shù)。
當我們調用生成器函數(shù)的時候,將會返回一個生成器。我們通過調用生成器的next()方法來執(zhí)行生成器函數(shù),直到拋出異常。
當執(zhí)行yield語句的時候,生成器對象是被凍結的,執(zhí)行的結果只有next()方法所返回的list。凍結的意思是除了next()方法可以返回一個列表以外,其他的變量都不會執(zhí)行。
把這段文檔簡單理解一下就是我們可以通過定義一個包含yield語句的函數(shù),來定義一個生成器函數(shù)。這個生成器函數(shù)可以通過next()方法來執(zhí)行。
下面我們舉個具體的栗子,來看一下yield的執(zhí)行原理。
首先我們定義了兩個函數(shù),yield_test()和yield_test2(),第一個函數(shù)是用return來返回輸出值,第二個函數(shù)用yield來返回。這樣做是為了反映return和yield的區(qū)別,也是為了體現(xiàn)包含yield語句函數(shù)的不同之處。為什么要做這個比較呢,說白了,yield語句其實也是返回一個值,只不過這個返回方式不太尋常,它是以生成器函數(shù)的形式返回,所以我們對比一下和return的區(qū)別,看看哪里不一樣。
# - * -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: ',
('The results2is: ',
('The type of results2 is: ',
('The result_list is:', [0, 1, 4, 9, 16])
"""
關于怎么分析Python生成器、迭代器與yield語句就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。