操屁眼的视频在线免费看,日本在线综合一区二区,久久在线观看免费视频,欧美日韩精品久久综

新聞資訊

    本文將主要分為4大部分,分別介紹核心編程中的迭代器、生成器 、閉包以及裝飾器。

    生成器

    生成器是生成一個值的特殊函數(shù),它具有這樣的特點:第一次執(zhí)行該函數(shù)時,先從頭按順序執(zhí)行,在碰到y(tǒng)ield關(guān)鍵字時該函數(shù)會暫停執(zhí)行該函數(shù)后續(xù)的代碼,并且返回一個值;在下一次調(diào)用該函數(shù)執(zhí)行時,程序?qū)纳弦淮螘和5奈恢美^續(xù)往下執(zhí)行。

    通過一個例子來理解生成器的執(zhí)行過程。求1-10的所有整數(shù)的立方并將結(jié)果打印輸出,正常使用列表的實現(xiàn)如下:

    def?lifang_ls():
    ?"""求1-10所用整數(shù)的立方數(shù)-列表方式實現(xiàn)"""
    ?ls = []
    ?for?i?in?range(1,11):
    ? ?result = i **?3
    ? ?ls.append(result)
    ?print(ls)

    if?__name__ ==?'__main__':
    ?lifang_ls()

    輸出結(jié)果如下:

    當(dāng)數(shù)據(jù)量很少時,可以很快得到結(jié)果。但是如果范圍擴(kuò)大到10000甚至是,就會發(fā)現(xiàn)程序執(zhí)行時間會變長,變卡,甚至有可能會因超出內(nèi)存空間而出現(xiàn)程序崩潰的現(xiàn)象。這是因為當(dāng)數(shù)據(jù)量變得非常大的時候,內(nèi)存需要開辟很大的空間去存儲這些數(shù)據(jù),內(nèi)存都被吃了,自然會變慢變卡。使用生成器就能解決這個問題。

    對于上述同一個問題用生成器實現(xiàn)如下,將范圍擴(kuò)大到1-:

    def?lifang_generate():
    ?"""求1-10000000所用整數(shù)的立方數(shù)-生成器方式實現(xiàn)"""
    ?for?i?in?range(1,10000001):
    ? ?result = i **?3
    ? ?yield?result

    if?__name__ ==?'__main__':
    ?G = lifang_generate()

    執(zhí)行效果如下:

    qq空間藍(lán)色鏈接生成器_生成自己qq空間鏈接_小蘋果 mp3鏈接qq空間背景音樂歌曲鏈接外鏈地址

    可以看到?jīng)]有任何的結(jié)果輸出,這說明程序已經(jīng)可以順利執(zhí)行。對于迭代器來講需要用next()方法來獲取值,修改主函數(shù)為以下情況可以打印輸出前4個整數(shù)的立方數(shù):

    if?__name__ ==?'__main__':
    ?G = lifang_generate()
    ?print(next(G))
    ?print(next(G))
    ?print(next(G))
    ?print(next(G))

    輸出結(jié)果如下:

    到此可以看到,生成器生成的值需要使用next()方法一個一個的取,它不會一次性生成所有的計算結(jié)果,只有在取值時才調(diào)用,這時程序會返回計算的一個值且程序暫停;下一次取值時從上一次中斷了的地方繼續(xù)往下執(zhí)行。

    以取出前3個值為例,下圖為生成器代碼解析圖:

    圖解:解釋器從上往下解釋代碼,首先是函數(shù)定義,這時在計算機(jī)內(nèi)存開辟了一片空間來存儲這個函數(shù),函數(shù)沒有被執(zhí)行,繼續(xù)往下解釋;到了主函數(shù)部分,首先執(zhí)行藍(lán)色箭頭1,接著往下執(zhí)行到藍(lán)色箭頭2第一次調(diào)用生成器取值,此時生成器函數(shù)()開始執(zhí)行,執(zhí)行到生成器函數(shù)()的藍(lán)色箭頭2碰到y(tǒng)ield關(guān)鍵字,這時候生成器函數(shù)暫停往下執(zhí)行并且將的結(jié)果返回,由于是第一次執(zhí)行,因此存儲著1的立方的值,此時將1返回,第54行代碼print(first)將結(jié)果打印輸出。

    主函數(shù)中程序接著往下執(zhí)行到藍(lán)色箭頭3,生成器函數(shù)()第二次被調(diào)用,與第一次不同,第二次從上一次(也就是第一次)暫停的位置繼續(xù)往下執(zhí)行,上一次停在了yield處,因此藍(lán)色箭頭3所作的事情就是執(zhí)行yield后面的語句,也就是第48行print('end'),執(zhí)行完成之后因for循環(huán)條件滿足,程序像第一次執(zhí)行那樣,執(zhí)行到y(tǒng)ield處暫停并返回一個值,此時返回的是2的立方數(shù),在第57行打印輸出8。

    第三次調(diào)用(藍(lán)色箭頭4)與第二次類似,在理清了執(zhí)行過程之后,程序執(zhí)行結(jié)果如下:

    生成自己qq空間鏈接_qq空間藍(lán)色鏈接生成器_小蘋果 mp3鏈接qq空間背景音樂歌曲鏈接外鏈地址

    迭代器

    這里先拋出兩個概念:可迭代對象、迭代器。

    凡是可以通過for循環(huán)遍歷其中的元素的對象,都是可迭代對象;之前學(xué)習(xí)得組合數(shù)據(jù)類型list(列表)、tuple(元組)、dict(字典)、集合(set)等,上一小節(jié)介紹得生成器也可以使用for循環(huán)來遍歷,因此,生成器也是迭代器,但迭代器不一定就是生成器,例如組合數(shù)據(jù)類型。

    凡是可以通過next訪問取值得對象均為迭代器,生成器就是一種迭代器。可以看到,生成器不僅可以用for循環(huán)來獲取值,還可以通過next()來獲取。

    中有一個庫,通過該庫的方法來判斷一個對象是否是可迭代對象;如果返回值為True則說明該對象為可迭代的,返回值為False則說明該對象為不可迭代。用方法來判斷一個對象是否是迭代器,根據(jù)返回值來判斷是否為迭代器。

    使用分別判斷列表,字典,字符串以及一個整數(shù)類型是否是可迭代對象的代碼如下:

    from?collections?import?Iterable

    def?isiterable():
    ?"""分別判斷列表,字典,字符串100,整形100是不是可迭代對象"""

    ?ls = isinstance([],Iterable)
    ?dic = isinstance({},Iterable)
    ?strs = isinstance('100',Iterable)
    ?ints = isinstance(100,Iterable)
    ?print('輸出True表示可迭代,F(xiàn)alse表示不可迭代\n\
    ?ls為{},dic為{},strs為{},ints為{}'
    .format(ls,dic,strs,ints))

    def?main():
    ?isiterable()
    ?
    if?__name__ ==?'__main__':
    ?main()

    執(zhí)行的輸出結(jié)果如下:

    使用判斷一個對象是否是迭代器的代碼如下,與判斷是否為可迭代對象類似:

    小蘋果 mp3鏈接qq空間背景音樂歌曲鏈接外鏈地址_生成自己qq空間鏈接_qq空間藍(lán)色鏈接生成器

    from?collections?import?Iterable,Iterator


    def?print_num():
    ?"""定義一個產(chǎn)生斐波那契數(shù)列的生成器"""
    ?a,b =?0,1
    ?for?i?in?range(1,10):
    ? ?yield?b
    ? ?a,b = b,a + b
    ?
    def?isiterator():
    ?"""分別判斷列表,字典、生成器是否為迭代器"""

    ?ls_ret = isinstance([],Iterator)
    ?dict_ret = isinstance({},Iterator)
    ?genarate_ret = isinstance((x *?2?for?i?in?range(10)),Iterator)
    ?print_num_ret = isinstance(print_num(),Iterator)
    ?print('輸出True表示該對象為迭代器,F(xiàn)alse表示該對象不是迭代器\n\
    ? ?ls輸出為{},dict輸出為{},genarate輸出為{},print_num輸出為{}'
    .format(ls_ret,dict_ret,genarate_ret,print_num_ret))

    def?main():
    ?isiterator()

    if?__name__ ==?'__main__':
    ?main()

    輸出的結(jié)果如下:

    組合數(shù)據(jù)類型不是迭代器,但是屬于可迭代對象,可以通過iter()函數(shù)將其轉(zhuǎn)換位迭代器,這樣就可以使用next方法來獲取對象各個元素的值,代碼如下:

    from?collections?import?Iterable,Iterator

    def?trans_to_iterator():
    ?"""使用iter()將可迭代類型-列表轉(zhuǎn)換為迭代器"""

    ?ls = [2,4,6,8,10]
    ?ls_ierator = iter(ls)
    ?ls_ierator_is = isinstance(ls_ierator,Iterator)
    ?print('轉(zhuǎn)換后的返回值為{},使用next取出的第一個元素的值為{}'.format(ls_ierator_is,next(ls_ierator)))
    def?main():
    ?trans_to_iterator()

    if?__name__ ==?'__main__':
    ?main()

    輸出結(jié)果為:

    閉包

    內(nèi)部函數(shù)對外部函數(shù)變量的引用,則將該函數(shù)與用到的變量稱為閉包。以下為閉包的例子:

    def?func(num):

    print('start')
    def?func_in():
    """閉包內(nèi)容"""
    ? new_num = num **?3
    ? print(new_num)
    return?func_in

    if?__name__ ==?'__main__':
    ret = func(10)
    ret()

    理解閉包是理解裝飾器的前提,同樣通過一張圖來理解閉包的執(zhí)行過程:

    生成自己qq空間鏈接_qq空間藍(lán)色鏈接生成器_小蘋果 mp3鏈接qq空間背景音樂歌曲鏈接外鏈地址

    圖解:解釋器從上往下解釋代碼qq空間藍(lán)色鏈接生成器,首先定義一個函數(shù),func指向了該函數(shù)(紅箭頭所示);接著到主函數(shù)執(zhí)行第14行代碼 ret = func(10),此時先執(zhí)行賦值號“=”右邊的內(nèi)容,這里調(diào)用了函數(shù)func()并傳入10這個實參,函數(shù)func()代碼開始執(zhí)行,先是打印輸出“start”,接著定義了一個函數(shù)(),指向了該函數(shù),函數(shù)沒有被調(diào)用,程序接著往下執(zhí)行, 將函數(shù)的引用返回,第14行代碼用ret接收了這個返回值,到此ret就指向了所指向的函數(shù)體(綠箭頭所示)。最后執(zhí)行ret所指的函數(shù)。這就是閉包的整個過程,()函數(shù)以及該函數(shù)內(nèi)用到的變量num就稱為閉包。

    裝飾器

    代碼的編寫需要遵循封閉開放原則,封閉是指對于已有的功能代碼實現(xiàn)不允許隨意進(jìn)行修改,開放是指能夠?qū)σ延械墓δ苓M(jìn)行擴(kuò)展。例如一款手游,現(xiàn)在已經(jīng)能夠?qū)崿F(xiàn)現(xiàn)有的游戲模式,但隨著外部環(huán)境的變化發(fā)展(市場競爭,用戶體驗等),現(xiàn)有的游戲模式已經(jīng)不能滿足用戶的需求了。為了留住用戶,需要加入更多的玩法來保持用戶對該款游戲的新鮮感,于是開發(fā)方在原來游戲的基礎(chǔ)上又開發(fā)了好幾種游戲模式。像這樣,新的游戲版本既增加了先的游戲模式,又保留了原有的游戲模式,體現(xiàn)了封閉開放的原則。 裝飾器的作用就是在不改變原來代碼的基礎(chǔ)上,在原來的功能上進(jìn)行拓展,保證開發(fā)的效率以及代碼的穩(wěn)定性。 打印輸出九九乘法表可以通過以下代碼實現(xiàn):

    def?func_1():
    """打印輸出九九乘法表"""
    for?i?in?range(1,10):
    ??for?j?in?range(1,i +?1):
    ? ? result = i * j
    ? ? print('{}*{}={}'.format(i,j,result),end=' ')
    ? print('')
    if?__name__ ==?'__main__':
    func_1()

    輸出結(jié)果如下:

    假如現(xiàn)在需要實現(xiàn)一個功能,在不修改函數(shù)代碼的前提下,在九九乘法表前增加一個表頭說明qq空間藍(lán)色鏈接生成器,在乘法表最后也增加一個說明。下面的代碼實現(xiàn)了裝飾器的功能:

    def?shuoming(func):
    def?shuoming_in():
    ? print('以下為九九乘法表:')
    ? func()
    ? print('以上為九九乘法表')
    return?shuoming_in

    def?func_1():
    """打印輸出九九乘法表"""
    for?i?in?range(1,10):
    ??for?j?in?range(1,i +?1):
    ? ? result = i * j
    ? ? print('{}*{}={}'.format(i,j,result),end=' ')
    ? print('')

    if?__name__ ==?'__main__':
    func_1 = shuoming(func_1)
    func_1()

    輸出結(jié)果如下:

    qq空間藍(lán)色鏈接生成器_生成自己qq空間鏈接_小蘋果 mp3鏈接qq空間背景音樂歌曲鏈接外鏈地址

    可以看到函數(shù)的代碼沒有任何修改,還實現(xiàn)了問題提出的要求,這其中的核心就在于最后兩行代碼。通過下圖來理解裝飾器執(zhí)行的過程:

    圖解:跟之前一樣,解釋器自上往下解釋代碼,遇到定義函數(shù)的代碼不用管,因為沒有調(diào)用函數(shù)是不會執(zhí)行的;這樣直接就來到了第22行代碼中,程序先執(zhí)行賦值號“=”右邊的代碼,()調(diào)用了之前定義的函數(shù),并傳入了實參,程序轉(zhuǎn)到(func)執(zhí)行,形參func接收實參,此時func也指向了所指向的函數(shù)(如圖中分界線上方白色方框內(nèi)的藍(lán)箭頭所示);在()函數(shù)中代碼繼續(xù)往下走,在()函數(shù)內(nèi)容又定義了一個()函數(shù)(如圖中分界線上方白色方框內(nèi)的藍(lán)色方框所示),接著往下,將()函數(shù)的引用返回,至此()函數(shù)執(zhí)行完畢,程序回到第22行代碼執(zhí)行,()函數(shù)的返回值被接收,此時,不在指向原來的函數(shù),轉(zhuǎn)成指向所指向的函數(shù)(如圖中分界線下方白色方框內(nèi)的黃色箭頭)。最后調(diào)用所指向的函數(shù),也就是()函數(shù),()函數(shù)內(nèi)的func指向了原來()所指的函數(shù)(也就是生成九九乘法表的函數(shù)),因此程序最終的結(jié)果就在九九乘法表前后各加了一個說明性字符串。

    以上為裝飾器的執(zhí)行過程,但是以上裝飾寫法不夠簡潔,大多數(shù)情況下采取以下寫法,輸出結(jié)果是一樣的:

    def?shuoming(func):
    ?def?shuoming_in():
    ? ?print('以下為九九乘法表:')
    ? ?func()
    ? ?print('以上為九九乘法表')
    ?return?shuoming_in

    """@shuoming相當(dāng)于func_1 = shuoming(fucn_1)"""
    @shuoming
    def?func_1():
    ?"""打印輸出九九乘法表"""
    ?for?i?in?range(1,10):
    ? ?for?j?in?range(1,i +?1):
    ? ? ?result = i * j
    ? ? ?print('{}*{}={}'.format(i,j,result),end=' ')
    ? ?print('')
    if?__name__ ==?'__main__':
    ?"""直接調(diào)用func_1即可完成裝飾"""
    ?func_1()

    有時候有些被裝飾的函數(shù)可能有以下幾種情況:存在或不存在參數(shù),有返回值或沒有返回值,參數(shù)可能定長或不定長等等,為了通用性,與爬蟲的請求代碼一樣,裝飾器有著通用的寫法:

    def?tongyong(func):
    def?tongyong_in(*args,**kwargs):
    ? ret = func(*args,**kwargs)
    ??return?ret
    return?tongyong_in

    使用這個裝飾器裝飾九九乘法表一樣可以正常輸出,如果需要特定的裝飾效果,修改這個通用代碼即可。

    結(jié)束

    以上為生成器、迭代器、閉包以及裝飾器的所有內(nèi)容,其中裝飾器屬于難點。理解裝飾器的執(zhí)行過程能夠更好的幫助我們進(jìn)階學(xué)習(xí)。

    — END —

    看完本文請分享一下吧!讓其他人也可以GET到新知識!

網(wǎng)站首頁   |    關(guān)于我們   |    公司新聞   |    產(chǎn)品方案   |    用戶案例   |    售后服務(wù)   |    合作伙伴   |    人才招聘   |   

友情鏈接: 餐飲加盟

地址:北京市海淀區(qū)    電話:010-     郵箱:@126.com

備案號:冀ICP備2024067069號-3 北京科技有限公司版權(quán)所有