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

Python筆記003-生成器和生成器表達式

系統 2119 0

Python筆記003-生成器和生成器表達式

以下是我學習《流暢的Python》后的個人筆記,現在拿出來和大家共享,希望能幫到各位Python學習者。

首次發表于: 微信公眾號:科技老丁哥,ID: TechDing,敬請關注。

本篇主要知識點:

  1. 生成器使用yield做關鍵字,一次只返回一個值給調用者,然后暫停執行,其作用是:節省內存空間。

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

  3. 生成器表達式可以認為是一種特殊的生成器,其代碼更簡潔,更容易理解,且和別的函數結合會更加靈活。

1. 生成器

生成器是Python中一個特殊的程序,用于控制循環的迭代行為。相對于一般函數用return來一次性返回所有值,生成器使用yield關鍵字,一次只返回一個值。

這樣的設計有很大的好處:在數據處理時,如果函數return出來的是一個非常大的數組,那么會非常占用內存,有時會報MemoryError的錯誤,而使用yield后一次僅僅返回一個元素值,可以優化內存占用的情況。

從這種角度來講,生成器函數每一次調用都返回一個元素值,這種特性使得生成器長得像函數,但行為卻像迭代器。

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

生成器并不像一般的函數,它返回一個值后,生成器函數會自動掛起,等到下一次調用時(使用其內部成員方法 __next__ 來實現),再返回到這個函數中繼續執行。

所以要想獲取生成器的元素值,需要通過成員方法next()來進行,比如:

            
              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
              
                )
              
              
                )
              
              
                # 報錯:StopIteration: 超過yield的所有元素
              
            
          

next()函數每次執行時,都會繼續執行掛起的生成器函數,直到執行完畢。

生成器的這種特點被稱為"延遲計算"或"惰性求值(Lazy evaluation)",可以有效的節省內存。惰性求值實際上是體現了協同程序的思想。

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

使用延遲計算后,可以極大的節省內存,比如對大文件進行讀取操作時,可以用下列生成器方法:

            
              
                ## 讀取大文件的生成器方法:
              
              
                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 
              
                # 一次只加載一個block到內存中,避免MemoryError
              
              
                else
              
              
                :
              
              
                return
              
            
          

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

            
              
                ## 使用close()可以隨時退出生成器
              
              
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. 生成器表達式

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

生成器表達式可以認為是一種特殊的生成器函數,類似于lambda表達式和普通函數。但是和生成器一樣,生成器表達式也是返回生成器generator對象,一次只返回一個值。

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

生成器表達式是一種特殊的生成器,所以它也有生成器的特性,可以使用for循環來獲取元素值,for循環內部自動調用了next()函數來執行。

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

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

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

首次發表于: 微信公眾號:科技老丁哥,ID: TechDing,敬請關注。

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

參考資料:

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

更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

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

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦?。。?/p>

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 亚洲欧美另类在线 | 在线观看国产一区亚洲bd | 护士一级毛片 | 国产一区二区在免费观看 | 变态 调教 视频 国产九色 | 久久国产精品男女热播 | 欧美激情一区二区三级高清视频 | 国产成人久久久精品一区二区三区 | 一区二区三区在线免费 | 视频福利一区 | 99日影院在线播放 | 国产人成精品免费视频 | 色五婷婷| 国产成人一区二区三区在线播放 | 久草新视频 | 一级毛片免费视频日本 | 久久精品国产99久久3d动漫 | 97影院九七影院理论片 | 四虎院影永久在线观看 | 午夜精品网站 | 国产福利在线小视频 | 曰本还a大片免费无播放器 曰本黄色录像 | 九九热视频在线播放 | 久久精品a一国产成人免费网站 | 黄色网址视频在线播放 | 亚洲欧美国产日产综合不卡 | 久久久久一级片 | 久久久免费| 天天看片夜夜爽 | 欧美日韩中文字幕一区二区高清 | 伊人22222 | 欧美不卡在线 | 男人午夜剧场 | 男女拍拍视频黄的全免费 | 欧美日韩在线成人免费视频大全 | 亚洲午夜天堂 | 国产无套免费网站 | 91久久青草精品38国产 | 久久免费视频7 | 动漫精品欧美一区二区三区 | 在线观看欧洲成人免费视频 |