亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

Python筆記003-生成器和生成器表達(dá)式

系統(tǒng) 2522 0

Python筆記003-生成器和生成器表達(dá)式

以下是我學(xué)習(xí)《流暢的Python》后的個(gè)人筆記,現(xiàn)在拿出來(lái)和大家共享,希望能幫到各位Python學(xué)習(xí)者。

首次發(fā)表于: 微信公眾號(hào):科技老丁哥,ID: TechDing,敬請(qǐng)關(guān)注。

本篇主要知識(shí)點(diǎn):

  1. 生成器使用yield做關(guān)鍵字,一次只返回一個(gè)值給調(diào)用者,然后暫停執(zhí)行,其作用是:節(jié)省內(nèi)存空間。

  2. 生成器可以用next()函數(shù),也可以用for迭代的方式獲取元素值,中間還可以用close()來(lái)隨時(shí)終止生成器。

  3. 生成器表達(dá)式可以認(rèn)為是一種特殊的生成器,其代碼更簡(jiǎn)潔,更容易理解,且和別的函數(shù)結(jié)合會(huì)更加靈活。

1. 生成器

生成器是Python中一個(gè)特殊的程序,用于控制循環(huán)的迭代行為。相對(duì)于一般函數(shù)用return來(lái)一次性返回所有值,生成器使用yield關(guān)鍵字,一次只返回一個(gè)值。

這樣的設(shè)計(jì)有很大的好處:在數(shù)據(jù)處理時(shí),如果函數(shù)return出來(lái)的是一個(gè)非常大的數(shù)組,那么會(huì)非常占用內(nèi)存,有時(shí)會(huì)報(bào)MemoryError的錯(cuò)誤,而使用yield后一次僅僅返回一個(gè)元素值,可以優(yōu)化內(nèi)存占用的情況。

從這種角度來(lái)講,生成器函數(shù)每一次調(diào)用都返回一個(gè)元素值,這種特性使得生成器長(zhǎng)得像函數(shù),但行為卻像迭代器。

            
              
                def
              
              
                squares
              
              
                (
              
              x
              
                )
              
              
                :
              
              
                # 計(jì)算0-x的所有數(shù)的平方
              
              
                #     return [i*i for i in range(x)] # 普通寫法,一次返回一個(gè)list,包含所有元素
              
              
                for
              
               i 
              
                in
              
              
                range
              
              
                (
              
              x
              
                )
              
              
                :
              
              
                yield
              
               i
              
                *
              
              i 
              
                # 生成器:一次只返回一個(gè)值
              
              
                print
              
              
                (
              
              squares
              
                (
              
              
                5
              
              
                )
              
              
                )
              
              
                # 
                
              
              
                # 獲取生成器中的元素值
              
              
                for
              
               value 
              
                in
              
               squares
              
                (
              
              
                5
              
              
                )
              
              
                :
              
              
                # 行為類似于迭代器,循環(huán)獲取元素值
              
              
                print
              
              
                (
              
              
                'value: '
              
              
                ,
              
              value
              
                )
              
            
          

生成器并不像一般的函數(shù),它返回一個(gè)值后,生成器函數(shù)會(huì)自動(dòng)掛起,等到下一次調(diào)用時(shí)(使用其內(nèi)部成員方法 __next__ 來(lái)實(shí)現(xiàn)),再返回到這個(gè)函數(shù)中繼續(xù)執(zhí)行。

所以要想獲取生成器的元素值,需要通過(guò)成員方法next()來(lái)進(jìn)行,比如:

            
              square_five
              
                =
              
              squares
              
                (
              
              
                5
              
              
                )
              
              
                print
              
              
                (
              
              
                next
              
              
                (
              
              square_five
              
                )
              
              
                )
              
              
                # 0
              
              
                print
              
              
                (
              
              
                next
              
              
                (
              
              square_five
              
                )
              
              
                )
              
              
                # 1
              
              
                print
              
              
                (
              
              
                next
              
              
                (
              
              square_five
              
                )
              
              
                )
              
              
                # 4
              
              
                print
              
              
                (
              
              
                next
              
              
                (
              
              square_five
              
                )
              
              
                )
              
              
                # 9
              
              
                print
              
              
                (
              
              
                next
              
              
                (
              
              square_five
              
                )
              
              
                )
              
              
                # 16
              
              
                print
              
              
                (
              
              
                next
              
              
                (
              
              square_five
              
                )
              
              
                )
              
              
                # 報(bào)錯(cuò):StopIteration: 超過(guò)yield的所有元素
              
            
          

next()函數(shù)每次執(zhí)行時(shí),都會(huì)繼續(xù)執(zhí)行掛起的生成器函數(shù),直到執(zhí)行完畢。

生成器的這種特點(diǎn)被稱為"延遲計(jì)算"或"惰性求值(Lazy evaluation)",可以有效的節(jié)省內(nèi)存。惰性求值實(shí)際上是體現(xiàn)了協(xié)同程序的思想。

雖然生成器的這種行為類似于迭代器,但兩者有較大差別,迭代器不具備這種執(zhí)行-暫停-再執(zhí)行-再暫停的特性,所以迭代器不具有延遲計(jì)算,沒有協(xié)同程序的思想。

使用延遲計(jì)算后,可以極大的節(jié)省內(nèi)存,比如對(duì)大文件進(jìn)行讀取操作時(shí),可以用下列生成器方法:

            
              
                ## 讀取大文件的生成器方法:
              
              
                def
              
              
                load_big_file
              
              
                (
              
              file_path
              
                )
              
              
                :
              
              
    BLOCK_SIZE 
              
                =
              
              
                1024
              
              
                with
              
              
                open
              
              
                (
              
              file_path
              
                ,
              
              
                'rb'
              
              
                )
              
              
                as
              
               f
              
                :
              
              
                while
              
              
                True
              
              
                :
              
              
            block 
              
                =
              
               f
              
                .
              
              read
              
                (
              
              BLOCK_SIZE
              
                )
              
              
                if
              
               block
              
                :
              
              
                yield
              
               block 
              
                # 一次只加載一個(gè)block到內(nèi)存中,避免MemoryError
              
              
                else
              
              
                :
              
              
                return
              
            
          

生成器除了用next()函數(shù)來(lái)處理之外,還可以用close()來(lái)隨時(shí)退出生成器。如下代碼:

            
              
                ## 使用close()可以隨時(shí)退出生成器
              
              
square_five
              
                =
              
              squares
              
                (
              
              
                5
              
              
                )
              
              
                print
              
              
                (
              
              
                next
              
              
                (
              
              square_five
              
                )
              
              
                )
              
              
                # 0
              
              
                print
              
              
                (
              
              
                next
              
              
                (
              
              square_five
              
                )
              
              
                )
              
              
                # 1
              
              
                print
              
              
                (
              
              
                next
              
              
                (
              
              square_five
              
                )
              
              
                )
              
              
                # 4
              
              
square_five
              
                .
              
              close
              
                (
              
              
                )
              
              
                # 退出生成器
              
              
                print
              
              
                (
              
              
                next
              
              
                (
              
              square_five
              
                )
              
              
                )
              
              
                # Error: StopIteration:
              
              
                print
              
              
                (
              
              
                next
              
              
                (
              
              square_five
              
                )
              
              
                )
              
              
                # Error: StopIteration:
              
            
          

2. 生成器表達(dá)式

從形式上來(lái)看,生成器表達(dá)式和列表推導(dǎo)式很像,僅僅是將列表推導(dǎo)式中的[]替換為(),但是兩者差別挺大,生成器表達(dá)式可以說(shuō)組合了迭代功能和列表解析功能。

生成器表達(dá)式可以認(rèn)為是一種特殊的生成器函數(shù),類似于lambda表達(dá)式和普通函數(shù)。但是和生成器一樣,生成器表達(dá)式也是返回生成器generator對(duì)象,一次只返回一個(gè)值。

            
              
                # 上面的squares函數(shù)可以改寫為:
              
              
                # 列表推導(dǎo)式的寫法是:
              
              
squares_list
              
                =
              
              
                [
              
              i
              
                *
              
              i 
              
                for
              
               i 
              
                in
              
              
                range
              
              
                (
              
              
                5
              
              
                )
              
              
                ]
              
              
                # 一次性返回整個(gè)list
              
              
                print
              
              
                (
              
              
                '列表推導(dǎo)式:'
              
              
                ,
              
              squares_list
              
                )
              
              
                # 列表推導(dǎo)式: [0, 1, 4, 9, 16]
              
              
                # 生成器表達(dá)式:
              
              
squares2
              
                =
              
              
                (
              
              i
              
                *
              
              i 
              
                for
              
               i 
              
                in
              
              
                range
              
              
                (
              
              
                5
              
              
                )
              
              
                )
              
              
                # 生成器表達(dá)式一次返回一個(gè)值
              
              
                print
              
              
                (
              
              
                '生成器表達(dá)式:'
              
              
                ,
              
              squares2
              
                )
              
              
                # 生成器表達(dá)式: 
                
                  
                    print
                  
                  
                    (
                  
                  
                    next
                  
                  
                    (
                  
                  squares2
                  
                    )
                  
                  
                    )
                  
                  
                    # 0
                  
                  
                    print
                  
                  
                    (
                  
                  
                    next
                  
                  
                    (
                  
                  squares2
                  
                    )
                  
                  
                    )
                  
                  
                    # 1
                  
                  
                    print
                  
                  
                    (
                  
                  
                    next
                  
                  
                    (
                  
                  squares2
                  
                    )
                  
                  
                    )
                  
                  
                    # 4
                  
                
              
            
          

生成器表達(dá)式是一種特殊的生成器,所以它也有生成器的特性,可以使用for循環(huán)來(lái)獲取元素值,for循環(huán)內(nèi)部自動(dòng)調(diào)用了next()函數(shù)來(lái)執(zhí)行。

            
              
                # generator對(duì)象可以直接用for來(lái)獲取所有元素值
              
              
squares2
              
                =
              
              
                (
              
              i
              
                *
              
              i 
              
                for
              
               i 
              
                in
              
              
                range
              
              
                (
              
              
                5
              
              
                )
              
              
                )
              
              
                # 生成器表達(dá)式就是一個(gè)generator對(duì)象
              
              
                for
              
               i 
              
                in
              
               squares2
              
                :
              
              
                print
              
              
                (
              
              
                'i: '
              
              
                ,
              
              i
              
                )
              
              
                # 上面可以簡(jiǎn)寫為:
              
              
                [
              
              
                print
              
              
                (
              
              
                'i: '
              
              
                ,
              
              i
              
                )
              
              
                for
              
               i 
              
                in
              
              
                (
              
              i
              
                *
              
              i 
              
                for
              
               i 
              
                in
              
              
                range
              
              
                (
              
              
                5
              
              
                )
              
              
                )
              
              
                ]
              
            
          

生成器表達(dá)式如果作為某個(gè)函數(shù)的參數(shù),則可以省略掉(),直接使用即可,eg:

            
              
                ## 如果生成器表達(dá)式整個(gè)作為某個(gè)函數(shù)的參數(shù),可以省略掉()
              
              
max_value
              
                =
              
              
                max
              
              
                (
              
              i
              
                *
              
              i 
              
                for
              
               i 
              
                in
              
              
                range
              
              
                (
              
              
                5
              
              
                )
              
              
                )
              
              
                # 計(jì)算生成器的所有元素中的最大值
              
              
                print
              
              
                (
              
              max_value
              
                )
              
              
                # 16
              
            
          

首次發(fā)表于: 微信公眾號(hào):科技老丁哥,ID: TechDing,敬請(qǐng)關(guān)注。

本文所有代碼都已經(jīng)上傳到我的github,歡迎下載

參考資料:

  1. 《流暢的Python》,Luciano Ramalho (作者) 安道 , 吳珂 (譯者)。

更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長(zhǎng)會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 日本在线色视频 | 免费一级毛片无毒不卡 | 国产一级毛片国语普通话对白 | 亚洲国产天堂久久精品网 | 亚洲国产成人在线 | 久久久久久尹人网香蕉 | 免费一看一级毛片 | 操你妹影院 | 农村苗族一级特黄a大片 | 国产伦码精品一区二区三区 | 伊人色综合久久天天网蜜月 | 亚洲精品永久一区 | 男人看的网址 | 天天做天天爱夜夜爽毛片毛片 | 日韩中文字幕久久精品 | 国产大片中文字幕 | 99在线观看 | 一区二区高清视频 | 九九视频免费观看 | 日韩欧美在线观看成人 | 精品亚洲一区二区在线播放 | 再猛点深使劲爽日本免费视频 | 国产精品视频在线观看 | 亚洲免费三区 | 成人免费看毛片 | 成人在线观看不卡 | 99在线观看视频免费 | 欧美日韩免费在线观看 | 国产一区二区不卡视频 | 天天射天天射天天干 | 四虎影视免费永久在线观看黄 | 久久久久久久国产视频 | 色婷婷综合和线在线 | 国产一区a| 日本无翼乌全彩无遮挡动漫 | 国产一级特黄aa毛片 | 精品国产综合区久久久久99 | 免费一级毛片在播放视频 | 日本叼嘿视频 | 综合在线视频精品专区 | 国产成人8x视频一区二区 |