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

python高級特性 __切片 、迭代 、列表生成式 、生成器 、迭代器

系統 1519 0
原文鏈接: https://www.liaoxuefeng.com/wiki/1016959663602400/1017318207388128

注:本篇博客是學習廖雪峰老師網站的摘抄,是為了方便以后的學習。
如有侵權,請聯系刪除!
聯系郵箱: 1103540209@qq.com

文章目錄

    • 1.切片
    • 2.迭代
    • 3.列表生成式
    • 4.生成器
    • 5.迭代器
    • 小結
    • 參考

掌握了Python的數據類型、語句和函數,基本上就可以編寫出很多有用的程序了。比如構造一個 1, 3, 5, 7, ..., 99 的列表,可以通過循環實現:

            
              L 
              
                =
              
              
                [
              
              
                ]
              
              
n 
              
                =
              
              
                1
              
              
                while
              
               n 
              
                <=
              
              
                99
              
              
                :
              
              
    L
              
                .
              
              append
              
                (
              
              n
              
                )
              
              
    n 
              
                =
              
               n 
              
                +
              
              
                2
              
            
          

取list的前一半的元素,也可以通過循環實現。
但是在Python中,代碼不是越多越好,而是越少越好。代碼不是越復雜越好,而是越簡單越好。
基于這一思想,我們來介紹Python中非常有用的高級特性,1行代碼能實現的功能,決不寫5行代碼。請始終牢記,代碼越少,開發效率越高。

1.切片

取一個list或tuple的部分元素是非常常見的操作。比如,一個list如下:

            
              L 
              
                =
              
              
                [
              
              
                'Michael'
              
              
                ,
              
              
                'Sarah'
              
              
                ,
              
              
                'Tracy'
              
              
                ,
              
              
                'Bob'
              
              
                ,
              
              
                'Jack'
              
              
                ]
              
            
          

取前3個元素,應該怎么做?
笨辦法:

            
              
                [
              
              L
              
                [
              
              
                0
              
              
                ]
              
              
                ,
              
               L
              
                [
              
              
                1
              
              
                ]
              
              
                ,
              
               L
              
                [
              
              
                2
              
              
                ]
              
              
                ]
              
            
          
            
              
                [
              
              
                'Michael'
              
              
                ,
              
              
                'Sarah'
              
              
                ,
              
              
                'Tracy'
              
              
                ]
              
            
          

之所以是笨辦法是因為擴展一下,取前N個元素就沒轍了。
取前N個元素,也就是索引為 0-(N-1) 的元素,可以用循環:

            
              r 
              
                =
              
              
                [
              
              
                ]
              
              
n 
              
                =
              
              
                3
              
              
                for
              
               i 
              
                in
              
              
                range
              
              
                (
              
              n
              
                )
              
              
                :
              
              
    r
              
                .
              
              append
              
                (
              
              L
              
                [
              
              i
              
                ]
              
              
                )
              
              
r

            
          
            
              
                [
              
              
                'Michael'
              
              
                ,
              
              
                'Sarah'
              
              
                ,
              
              
                'Tracy'
              
              
                ]
              
            
          

對這種經常取指定索引范圍的操作,用循環十分繁瑣,因此,Python提供了切片(Slice)操作符,能大大簡化這種操作。
對應上面的問題,取前3個元素,用一行代碼就可以完成切片:

            
              L
              
                [
              
              
                0
              
              
                :
              
              
                3
              
              
                ]
              
            
          
            
              
                [
              
              
                'Michael'
              
              
                ,
              
              
                'Sarah'
              
              
                ,
              
              
                'Tracy'
              
              
                ]
              
            
          

L[0:3] 表示,從索引0開始取,直到索引3為止,但不包括索引3。即索引0,1,2,正好是3個元素。
如果第一個索引是0,還可以省略:

            
               L
              
                [
              
              
                :
              
              
                3
              
              
                ]
              
            
          
            
              
                [
              
              
                'Michael'
              
              
                ,
              
              
                'Sarah'
              
              
                ,
              
              
                'Tracy'
              
              
                ]
              
            
          

也可以從索引1開始,取出2個元素出來:

            
              L
              
                [
              
              
                1
              
              
                :
              
              
                3
              
              
                ]
              
            
          
            
              
                [
              
              
                'Sarah'
              
              
                ,
              
              
                'Tracy'
              
              
                ]
              
            
          

類似的,既然Python支持 L[-1] 取倒數第一個元素,那么它同樣支持倒數切片,試試:

            
               L
              
                [
              
              
                -
              
              
                2
              
              
                :
              
              
                ]
              
            
          
            
              
                [
              
              
                'Bob'
              
              
                ,
              
              
                'Jack'
              
              
                ]
              
            
          
            
              L
              
                [
              
              
                -
              
              
                2
              
              
                :
              
              
                -
              
              
                1
              
              
                ]
              
            
          
            
              
                [
              
              
                'Bob'
              
              
                ]
              
            
          

記住倒數第一個元素的索引是-1。
切片操作十分有用。我們先創建一個0-99的數列:

            
              L 
              
                =
              
              
                list
              
              
                (
              
              
                range
              
              
                (
              
              
                100
              
              
                )
              
              
                )
              
            
          

可以通過切片輕松取出某一段數列。比如前10個數:

            
               L
              
                [
              
              
                :
              
              
                10
              
              
                ]
              
            
          
            
              
                [
              
              
                0
              
              
                ,
              
              
                1
              
              
                ,
              
              
                2
              
              
                ,
              
              
                3
              
              
                ,
              
              
                4
              
              
                ,
              
              
                5
              
              
                ,
              
              
                6
              
              
                ,
              
              
                7
              
              
                ,
              
              
                8
              
              
                ,
              
              
                9
              
              
                ]
              
            
          

后10個數:

            
               L
              
                [
              
              
                -
              
              
                10
              
              
                :
              
              
                ]
              
            
          
            
              
                [
              
              
                90
              
              
                ,
              
              
                91
              
              
                ,
              
              
                92
              
              
                ,
              
              
                93
              
              
                ,
              
              
                94
              
              
                ,
              
              
                95
              
              
                ,
              
              
                96
              
              
                ,
              
              
                97
              
              
                ,
              
              
                98
              
              
                ,
              
              
                99
              
              
                ]
              
            
          

前11-20個數:

            
               L
              
                [
              
              
                10
              
              
                :
              
              
                20
              
              
                ]
              
            
          
            
              
                [
              
              
                10
              
              
                ,
              
              
                11
              
              
                ,
              
              
                12
              
              
                ,
              
              
                13
              
              
                ,
              
              
                14
              
              
                ,
              
              
                15
              
              
                ,
              
              
                16
              
              
                ,
              
              
                17
              
              
                ,
              
              
                18
              
              
                ,
              
              
                19
              
              
                ]
              
            
          

前10個數,每兩個取一個:

            
               L
              
                [
              
              
                :
              
              
                10
              
              
                :
              
              
                2
              
              
                ]
              
            
          
            
              
                [
              
              
                0
              
              
                ,
              
              
                2
              
              
                ,
              
              
                4
              
              
                ,
              
              
                6
              
              
                ,
              
              
                8
              
              
                ]
              
            
          

所有數,每5個取一個:

            
               L
              
                [
              
              
                :
              
              
                :
              
              
                5
              
              
                ]
              
            
          
            
              
                [
              
              
                0
              
              
                ,
              
              
                5
              
              
                ,
              
              
                10
              
              
                ,
              
              
                15
              
              
                ,
              
              
                20
              
              
                ,
              
              
                25
              
              
                ,
              
              
                30
              
              
                ,
              
              
                35
              
              
                ,
              
              
                40
              
              
                ,
              
              
                45
              
              
                ,
              
              
                50
              
              
                ,
              
              
                55
              
              
                ,
              
              
                60
              
              
                ,
              
              
                65
              
              
                ,
              
              
                70
              
              
                ,
              
              
                75
              
              
                ,
              
              
                80
              
              
                ,
              
              
                85
              
              
                ,
              
              
                90
              
              
                ,
              
              
                95
              
              
                ]
              
            
          

甚至什么都不寫,只寫 [:] 就可以原樣復制一個 list

            
               L
              
                [
              
              
                :
              
              
                ]
              
            
          
            
              [0,
 1,
 2,
 3,
 4,
 5,
 6,
 7,
 8,
 9,
 10,
 11,
 12,
 13,
 14,
 15,
 16,
 17,
 18,
 19,
 20,
 21,
 22,
 23,
 24,
 25,
 26,
 27,
 28,
 29,
 30,
 31,
 32,
 33,
 34,
 35,
 36,
 37,
 38,
 39,
 40,
 41,
 42,
 43,
 44,
 45,
 46,
 47,
 48,
 49,
 50,
 51,
 52,
 53,
 54,
 55,
 56,
 57,
 58,
 59,
 60,
 61,
 62,
 63,
 64,
 65,
 66,
 67,
 68,
 69,
 70,
 71,
 72,
 73,
 74,
 75,
 76,
 77,
 78,
 79,
 80,
 81,
 82,
 83,
 84,
 85,
 86,
 87,
 88,
 89,
 90,
 91,
 92,
 93,
 94,
 95,
 96,
 97,
 98,
 99]

            
          

tuple 也是一種 list ,唯一區別是 tuple 不可變。因此, tuple 也可以用切片操作,只是操作的結果仍是 tuple

            
              
                (
              
              
                0
              
              
                ,
              
              
                1
              
              
                ,
              
              
                2
              
              
                ,
              
              
                3
              
              
                ,
              
              
                4
              
              
                ,
              
              
                5
              
              
                )
              
              
                [
              
              
                :
              
              
                3
              
              
                ]
              
            
          
            
              
                (
              
              
                0
              
              
                ,
              
              
                1
              
              
                ,
              
              
                2
              
              
                )
              
            
          

字符串 'xxx' 也可以看成是一種 list ,每個元素就是一個字符。因此,字符串也可以用切片操作,只是操作結果仍是字符串:

            
              
                'ABCDEFG'
              
              
                [
              
              
                :
              
              
                3
              
              
                ]
              
            
          
            
              
                'ABC'
              
            
          
            
              
                'ABCDEFG'
              
              
                [
              
              
                :
              
              
                :
              
              
                2
              
              
                ]
              
            
          
            
              
                'ACEG'
              
            
          

在很多編程語言中,針對字符串提供了很多各種截取函數(例如,substring),其實目的就是對字符串切片。Python沒有針對字符串的截取函數,只需要切片一個操作就可以完成,非常簡單。

2.迭代

如果給定一個 lis t或 tuple ,我們可以通過 for循環 來遍歷這個 list tuple ,這種遍歷我們稱為迭代 (Iteration)
在Python中,迭代是通過 for ... in 來完成的,而很多語言比如C語言,迭代 list 是通過下標完成的,比如Java代碼:

            
              
                for
              
              
                (
              
              i
              
                =
              
              
                0
              
              
                ;
              
               i
              
                <
              
              list
              
                .
              
              length
              
                ;
              
               i
              
                ++
              
              
                )
              
              
                {
              
              
    n 
              
                =
              
               list
              
                [
              
              i
              
                ]
              
              
                ;
              
              
                }
              
            
          

可以看出,Python的 for循環 抽象程度要高于C的 for循環 ,因為Python的 for循環 不僅可以用在 list tuple 上,還可以作用在其他可迭代對象上。
list 這種數據類型雖然有下標,但很多其他數據類型是沒有下標的,但是,只要是 可迭代對象 ,無論有無下標,都可以迭代,比如 dict 就可以迭代:

            
              d 
              
                =
              
              
                {
              
              
                'a'
              
              
                :
              
              
                1
              
              
                ,
              
              
                'b'
              
              
                :
              
              
                2
              
              
                ,
              
              
                'c'
              
              
                :
              
              
                3
              
              
                }
              
              
                for
              
               key 
              
                in
              
               d
              
                :
              
              
                print
              
              
                (
              
              key
              
                )
              
            
          
            
              a
b
c

            
          

因為 dict 的存儲不是按照 list 的方式順序排列,所以,迭代出的結果順序很可能不一樣。
默認情況下, dict 迭代的是 key 。如果要迭代 value ,可以用 for value in d.values() ,如果要同時迭代 key value ,可以用 for k, v in d.items()
由于字符串也是可迭代對象,因此,也可以作用于 for循環

            
              
                for
              
               ch 
              
                in
              
              
                'ABC'
              
              
                :
              
              
                print
              
              
                (
              
              ch
              
                )
              
            
          
            
              A
B
C

            
          

所以,當我們使用 for循環 時,只要作用于一個可迭代對象, for循環 就可以正常運行,而我們不太關心該對象究竟是 list 還是其他數據類型。
那么,如何判斷一個對象是可迭代對象呢?方法是通過collections模塊的 Iterable 類型判斷:

            
              
                from
              
               collections 
              
                import
              
               Iterable


              
                isinstance
              
              
                (
              
              
                'abc'
              
              
                ,
              
               Iterable
              
                )
              
              
                # str是否可迭代
              
            
          
            
              
                True
              
            
          
            
              
                isinstance
              
              
                (
              
              
                [
              
              
                1
              
              
                ,
              
              
                2
              
              
                ,
              
              
                3
              
              
                ]
              
              
                ,
              
               Iterable
              
                )
              
              
                # list是否可迭代
              
            
          
            
              
                True
              
            
          
            
              
                isinstance
              
              
                (
              
              
                123
              
              
                ,
              
               Iterable
              
                )
              
              
                # 整數是否可迭代
              
            
          
            
              
                False
              
            
          

最后一個小問題,如果要對 list 實現類似Java那樣的下標循環怎么辦?Python內置的 enumerate函數 可以把一個 list 變成 索引-元素對 ,這樣就可以在 for循環 中同時迭代索引和元素本身:

            
              
                for
              
               i
              
                ,
              
               value 
              
                in
              
              
                enumerate
              
              
                (
              
              
                [
              
              
                'A'
              
              
                ,
              
              
                'B'
              
              
                ,
              
              
                'C'
              
              
                ]
              
              
                )
              
              
                :
              
              
                print
              
              
                (
              
              i
              
                ,
              
               value
              
                )
              
            
          
            
              
                0
              
               A

              
                1
              
               B

              
                2
              
               C

            
          

上面的for循環里,同時引用了兩個變量,在Python里是很常見的,比如下面的代碼:

            
              
                for
              
               x
              
                ,
              
               y 
              
                in
              
              
                [
              
              
                (
              
              
                1
              
              
                ,
              
              
                1
              
              
                )
              
              
                ,
              
              
                (
              
              
                2
              
              
                ,
              
              
                4
              
              
                )
              
              
                ,
              
              
                (
              
              
                3
              
              
                ,
              
              
                9
              
              
                )
              
              
                ]
              
              
                :
              
              
                print
              
              
                (
              
              x
              
                ,
              
               y
              
                )
              
            
          
            
              
                1
              
              
                1
              
              
                2
              
              
                4
              
              
                3
              
              
                9
              
            
          

3.列表生成式

列表生成式即 List Comprehensions ,是Python內置的非常簡單卻強大的可以用來創建 list 的生成式。
舉個例子,要生成list [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 可以用 list(range(1, 11))

            
              
                list
              
              
                (
              
              
                range
              
              
                (
              
              
                1
              
              
                ,
              
              
                11
              
              
                )
              
              
                )
              
            
          
            
              
                [
              
              
                1
              
              
                ,
              
              
                2
              
              
                ,
              
              
                3
              
              
                ,
              
              
                4
              
              
                ,
              
              
                5
              
              
                ,
              
              
                6
              
              
                ,
              
              
                7
              
              
                ,
              
              
                8
              
              
                ,
              
              
                9
              
              
                ,
              
              
                10
              
              
                ]
              
            
          

但如果要生成 [1x1, 2x2, 3x3, ..., 10x10] 怎么做?方法一是循環:

            
              L 
              
                =
              
              
                [
              
              
                ]
              
              
                for
              
               x 
              
                in
              
              
                range
              
              
                (
              
              
                1
              
              
                ,
              
              
                11
              
              
                )
              
              
                :
              
              
    L
              
                .
              
              append
              
                (
              
              x 
              
                *
              
               x
              
                )
              
              

L

            
          
            
              
                [
              
              
                1
              
              
                ,
              
              
                4
              
              
                ,
              
              
                9
              
              
                ,
              
              
                16
              
              
                ,
              
              
                25
              
              
                ,
              
              
                36
              
              
                ,
              
              
                49
              
              
                ,
              
              
                64
              
              
                ,
              
              
                81
              
              
                ,
              
              
                100
              
              
                ]
              
            
          

但是循環太繁瑣,而列表生成式則可以用一行語句代替循環生成上面的 list

            
              
                [
              
              x 
              
                *
              
               x 
              
                for
              
               x 
              
                in
              
              
                range
              
              
                (
              
              
                1
              
              
                ,
              
              
                11
              
              
                )
              
              
                ]
              
            
          
            
              
                [
              
              
                1
              
              
                ,
              
              
                4
              
              
                ,
              
              
                9
              
              
                ,
              
              
                16
              
              
                ,
              
              
                25
              
              
                ,
              
              
                36
              
              
                ,
              
              
                49
              
              
                ,
              
              
                64
              
              
                ,
              
              
                81
              
              
                ,
              
              
                100
              
              
                ]
              
            
          

寫列表生成式時,把要生成的元素 x * x 放到前面,后面跟 for循環 ,就可以把 list 創建出來,十分有用,多寫幾次,很快就可以熟悉這種語法。
for循環 后面還可以加上 if判斷 ,這樣我們就可以篩選出僅偶數的平方:

            
              
                [
              
              x 
              
                *
              
               x 
              
                for
              
               x 
              
                in
              
              
                range
              
              
                (
              
              
                1
              
              
                ,
              
              
                11
              
              
                )
              
              
                if
              
               x 
              
                %
              
              
                2
              
              
                ==
              
              
                0
              
              
                ]
              
            
          
            
              
                [
              
              
                4
              
              
                ,
              
              
                16
              
              
                ,
              
              
                36
              
              
                ,
              
              
                64
              
              
                ,
              
              
                100
              
              
                ]
              
            
          

還可以使用兩層循環,可以生成全排列:

            
              
                [
              
              m 
              
                +
              
               n 
              
                for
              
               m 
              
                in
              
              
                'ABC'
              
              
                for
              
               n 
              
                in
              
              
                'XYZ'
              
              
                ]
              
            
          
            
              
                [
              
              
                'AX'
              
              
                ,
              
              
                'AY'
              
              
                ,
              
              
                'AZ'
              
              
                ,
              
              
                'BX'
              
              
                ,
              
              
                'BY'
              
              
                ,
              
              
                'BZ'
              
              
                ,
              
              
                'CX'
              
              
                ,
              
              
                'CY'
              
              
                ,
              
              
                'CZ'
              
              
                ]
              
            
          

三層和三層以上的循環就很少用到了。
運用列表生成式,可以寫出非常簡潔的代碼。例如,列出當前目錄下的所有文件和目錄名,可以通過一行代碼實現:

            
              
                import
              
               os 
              
                # 導入os模塊
              
              
                [
              
              d 
              
                for
              
               d 
              
                in
              
               os
              
                .
              
              listdir
              
                (
              
              
                '.'
              
              
                )
              
              
                ]
              
              
                # os.listdir可以列出文件和目錄
              
            
          
            
              
                [
              
              
                '.ipynb_checkpoints'
              
              
                ,
              
              
                'args 和 kwargs的用法.ipynb'
              
              
                ,
              
              
                'data'
              
              
                ,
              
              
                'pandas 表的合并 merge、join、contact.ipynb'
              
              
                ,
              
              
                'Pandas合并連接merge.ipynb'
              
              
                ,
              
              
                'pandas數據合并與重塑(pd.concat篇).ipynb'
              
              
                ,
              
              
                'picture'
              
              
                ,
              
              
                'Python3中的編碼問題(Unicode, UTF-8, GBK, ASCII).ipynb'
              
              
                ,
              
              
                'Python創建類、構造函數和析構函數、創建實例對象.ipynb'
              
              
                ,
              
              
                'Python異常及處理方法總結.ipynb'
              
              
                ,
              
              
                'python的定時器.ipynb'
              
              
                ,
              
              
                'python的類.ipynb'
              
              
                ,
              
              
                'tqdm介紹及常用方法.ipynb'
              
              
                ,
              
              
                'Untitled.ipynb'
              
              
                ,
              
              
                'urlencode與unquote.ipynb'
              
              
                ,
              
              
                '玩轉Python類的(私有)屬性與方法的使用.ipynb'
              
              
                ,
              
              
                '面向對象編程.ipynb'
              
              
                ]
              
            
          

for循環 其實可以同時使用兩個甚至多個變量,比如 dict items() 可以同時迭代 key value

            
              d 
              
                =
              
              
                {
              
              
                'x'
              
              
                :
              
              
                'A'
              
              
                ,
              
              
                'y'
              
              
                :
              
              
                'B'
              
              
                ,
              
              
                'z'
              
              
                :
              
              
                'C'
              
              
                }
              
              
                for
              
               k
              
                ,
              
               v 
              
                in
              
               d
              
                .
              
              items
              
                (
              
              
                )
              
              
                :
              
              
                print
              
              
                (
              
              k
              
                ,
              
              
                '='
              
              
                ,
              
               v
              
                )
              
            
          
            
              x 
              
                =
              
               A
y 
              
                =
              
               B
z 
              
                =
              
               C

            
          

因此,列表生成式也可以使用兩個變量來生成 list

            
              d 
              
                =
              
              
                {
              
              
                'x'
              
              
                :
              
              
                'A'
              
              
                ,
              
              
                'y'
              
              
                :
              
              
                'B'
              
              
                ,
              
              
                'z'
              
              
                :
              
              
                'C'
              
              
                }
              
              
                [
              
              k 
              
                +
              
              
                '='
              
              
                +
              
               v 
              
                for
              
               k
              
                ,
              
               v 
              
                in
              
               d
              
                .
              
              items
              
                (
              
              
                )
              
              
                ]
              
            
          
            
              
                [
              
              
                'x=A'
              
              
                ,
              
              
                'y=B'
              
              
                ,
              
              
                'z=C'
              
              
                ]
              
            
          

最后把一個 list 中所有的字符串變成小寫:

            
              L 
              
                =
              
              
                [
              
              
                'Hello'
              
              
                ,
              
              
                'World'
              
              
                ,
              
              
                'IBM'
              
              
                ,
              
              
                'Apple'
              
              
                ]
              
              
                [
              
              s
              
                .
              
              lower
              
                (
              
              
                )
              
              
                for
              
               s 
              
                in
              
               L
              
                ]
              
            
          
            
              
                [
              
              
                'hello'
              
              
                ,
              
              
                'world'
              
              
                ,
              
              
                'ibm'
              
              
                ,
              
              
                'apple'
              
              
                ]
              
            
          

4.生成器

通過列表生成式,我們可以直接創建一個列表。但是,受到內存限制,列表容量肯定是有限的。而且,創建一個包含100萬個元素的列表,不僅占用很大的存儲空間,如果我們僅僅需要訪問前面幾個元素,那后面絕大多數元素占用的空間都白白浪費了。
所以, 如果列表元素可以按照某種算法推算出來,那我們是否可以在循環的過程中不斷推算出后續的元素呢?這樣就不必創建完整的 list ,從而節省大量的空間。在Python中,這種一邊循環一邊計算的機制,稱為生成器: generator
要創建一個 generator ,有很多種方法。第一種方法很簡單,只要把一個列表生成式的 [] 改成 () ,就創建了一個 generator

            
              L 
              
                =
              
              
                [
              
              x 
              
                *
              
               x 
              
                for
              
               x 
              
                in
              
              
                range
              
              
                (
              
              
                10
              
              
                )
              
              
                ]
              
              
L

            
          
            
              
                [
              
              
                0
              
              
                ,
              
              
                1
              
              
                ,
              
              
                4
              
              
                ,
              
              
                9
              
              
                ,
              
              
                16
              
              
                ,
              
              
                25
              
              
                ,
              
              
                36
              
              
                ,
              
              
                49
              
              
                ,
              
              
                64
              
              
                ,
              
              
                81
              
              
                ]
              
            
          
            
              g 
              
                =
              
              
                (
              
              x 
              
                *
              
               x 
              
                for
              
               x 
              
                in
              
              
                range
              
              
                (
              
              
                10
              
              
                )
              
              
                )
              
              
g

            
          
            
              
                <
              
              generator 
              
                object
              
              
                <
              
              genexpr
              
                >
              
               at 
              
                0x00000187C250CF10
              
              
                >
              
            
          

創建 L g 的區別僅在于最外層的 [] () ,L是一個 list ,而g是一個 generator
我們可以直接打印出 list 的每一個元素,但我們怎么打印出 generator 的每一個元素呢?
如果要一個一個打印出來,可以通過 next() 函數獲得 generator 的下一個返回值:

            
              
                next
              
              
                (
              
              g
              
                )
              
            
          
            
              0

            
          
            
              
                next
              
              
                (
              
              g
              
                )
              
            
          
            
              1

            
          
            
              
                next
              
              
                (
              
              g
              
                )
              
            
          
            
              9

            
          
            
              
                next
              
              
                (
              
              g
              
                )
              
            
          
            
              16

            
          
            
              
                next
              
              
                (
              
              g
              
                )
              
            
          
            
              25

            
          
            
              
                next
              
              
                (
              
              g
              
                )
              
            
          
            
              36

            
          
            
              
                next
              
              
                (
              
              g
              
                )
              
            
          
            
              49

            
          
            
              
                next
              
              
                (
              
              g
              
                )
              
            
          
            
              64

            
          
            
              
                next
              
              
                (
              
              g
              
                )
              
            
          
            
              81

            
          
            
              
                next
              
              
                (
              
              g
              
                )
              
            
          
            
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              

StopIteration                             Traceback 
              
                (
              
              most recent call last
              
                )
              
              
                <
              
              ipython
              
                -
              
              
                input
              
              
                -
              
              
                61
              
              
                -
              
              e734f8aca5ac
              
                >
              
              
                in
              
              
                <
              
              module
              
                >
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                >
              
              
                1
              
              
                next
              
              
                (
              
              g
              
                )
              
            
          
            
              StopIteration
              
                :
              
            
          

我們講過, generator 保存的是算法,每次調用 next(g) ,就計算出g的下一個元素的值,直到計算到最后一個元素,沒有更多的元素時,拋出 StopIteration 的錯誤。
當然,上面這種不斷調用 next(g) 實在是太變態了,正確的方法是使用 for循環 ,因為 generator 也是可迭代對象:

            
              g 
              
                =
              
              
                (
              
              x 
              
                *
              
               x 
              
                for
              
               x 
              
                in
              
              
                range
              
              
                (
              
              
                10
              
              
                )
              
              
                )
              
              
                for
              
               n 
              
                in
              
               g
              
                :
              
              
                print
              
              
                (
              
              n
              
                )
              
            
          
            
              
                0
              
              
                1
              
              
                4
              
              
                9
              
              
                16
              
              
                25
              
              
                36
              
              
                49
              
              
                64
              
              
                81
              
            
          

所以,我們創建了一個 generator 后,基本上永遠不會調用 next() ,而是通過 for循環 來迭代它,并且不需要關心 StopIteration 的錯誤。
generator 非常強大。如果推算的算法比較復雜,用類似列表生成式的 for循環 無法實現的時候,還可以用函數來實現。
比如,著名的斐波拉契數列(Fibonacci),除第一個和第二個數外,任意一個數都可由前兩個數相加得到:
1, 1, 2, 3, 5, 8, 13, 21, 34, ...
斐波拉契數列用列表生成式寫不出來,但是,用函數把它打印出來卻很容易:

            
              
                def
              
              
                fib
              
              
                (
              
              
                max
              
              
                )
              
              
                :
              
              
    n
              
                ,
              
               a
              
                ,
              
               b 
              
                =
              
              
                0
              
              
                ,
              
              
                0
              
              
                ,
              
              
                1
              
              
                while
              
               n 
              
                <
              
              
                max
              
              
                :
              
              
                print
              
              
                (
              
              b
              
                )
              
              
        a
              
                ,
              
               b 
              
                =
              
               b
              
                ,
              
               a 
              
                +
              
               b
        n 
              
                =
              
               n 
              
                +
              
              
                1
              
              
                return
              
              
                'done'
              
            
          

注意,賦值語句:
a, b = b, a + b

相當于:
t = (b, a + b) # t是一個tuple a = t[0] b = t[1]

但不必顯式寫出臨時變量t就可以賦值。
上面的函數可以輸出斐波那契數列的前N個數:

            
               fib
              
                (
              
              
                6
              
              
                )
              
            
          
            
              
                1
              
              
                1
              
              
                2
              
              
                3
              
              
                5
              
              
                8
              
            
          
            
              
                'done'
              
            
          

仔細觀察,可以看出,fib函數實際上是定義了斐波拉契數列的推算規則,可以從第一個元素開始,推算出后續任意的元素,這種邏輯其實非常類似 generator
也就是說,上面的函數和 generator 僅一步之遙。要把fib函數變成 generator ,只需要把 print(b) 改為 yield b 就可以了:

            
              
                def
              
              
                fib
              
              
                (
              
              
                max
              
              
                )
              
              
                :
              
              
    n
              
                ,
              
               a
              
                ,
              
               b 
              
                =
              
              
                0
              
              
                ,
              
              
                0
              
              
                ,
              
              
                1
              
              
                while
              
               n 
              
                <
              
              
                max
              
              
                :
              
              
                yield
              
               b
        a
              
                ,
              
               b 
              
                =
              
               b
              
                ,
              
               a 
              
                +
              
               b
        n 
              
                =
              
               n 
              
                +
              
              
                1
              
              
                return
              
              
                'done'
              
            
          

這就是定義 generator 的另一種方法。如果一個函數定義中包含 yield 關鍵字,那么這個函數就不再是一個普通函數,而是一個 generator

            
              f 
              
                =
              
               fib
              
                (
              
              
                6
              
              
                )
              
              
f

            
          
            
              
                <
              
              generator 
              
                object
              
               fib at 
              
                0x00000187C25B8830
              
              
                >
              
            
          

這里,最難理解的就是 generator 和函數的執行流程不一樣。函數是順序執行,遇到return語句或者最后一行函數語句就返回。而變成 generator 的函數,在每次調用 next() 的時候執行,遇到 yield 語句返回,再次執行時從上次返回的 yield 語句處繼續執行。
舉個簡單的例子,定義一個 generator ,依次返回數字1,3,5:

            
              
                def
              
              
                odd
              
              
                (
              
              
                )
              
              
                :
              
              
                print
              
              
                (
              
              
                'step 1'
              
              
                )
              
              
                yield
              
              
                1
              
              
                print
              
              
                (
              
              
                'step 2'
              
              
                )
              
              
                yield
              
              
                (
              
              
                3
              
              
                )
              
              
                print
              
              
                (
              
              
                'step 3'
              
              
                )
              
              
                yield
              
              
                (
              
              
                5
              
              
                )
              
            
          

調用該 generator 時,首先要生成一個 generator 對象,然后用 next() 函數不斷獲得下一個返回值:

            
              o 
              
                =
              
               odd
              
                (
              
              
                )
              
            
          
            
              
                next
              
              
                (
              
              o
              
                )
              
            
          
            
              step 
              
                1
              
            
          
            
              
                1
              
            
          
            
              
                next
              
              
                (
              
              o
              
                )
              
            
          
            
              step 
              
                2
              
            
          
            
              
                3
              
            
          
            
              
                next
              
              
                (
              
              o
              
                )
              
            
          
            
              step 
              
                3
              
            
          
            
              
                5
              
            
          
            
              
                next
              
              
                (
              
              o
              
                )
              
            
          
            
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              

StopIteration                             Traceback 
              
                (
              
              most recent call last
              
                )
              
              
                <
              
              ipython
              
                -
              
              
                input
              
              
                -
              
              
                75
              
              
                -
              
              ac94be31f4f2
              
                >
              
              
                in
              
              
                <
              
              module
              
                >
              
              
                -
              
              
                -
              
              
                -
              
              
                -
              
              
                >
              
              
                1
              
              
                next
              
              
                (
              
              o
              
                )
              
            
          
            
              StopIteration
              
                :
              
            
          

可以看到, odd 不是普通函數,而是 generator ,在執行過程中,遇到 yield 就中斷,下次又繼續執行。執行3次 yield 后,已經沒有 yield 可以執行了,所以,第4次調用 next(o) 就報錯。
回到fib的例子,我們在循環過程中不斷調用 yield ,就會不斷中斷。當然要給循環設置一個條件來退出循環,不然就會產生一個無限數列出來。
同樣的,把函數改成 generator 后,我們基本上從來不會用 next() 來獲取下一個返回值,而是直接使用 for循環 來迭代:

            
              
                for
              
               n 
              
                in
              
               fib
              
                (
              
              
                6
              
              
                )
              
              
                :
              
              
                print
              
              
                (
              
              n
              
                )
              
            
          
            
              
                1
              
              
                1
              
              
                2
              
              
                3
              
              
                5
              
              
                8
              
            
          

但是用 for循環 調用 generator 時,發現拿不到 generator return 語句的返回值。如果想要拿到返回值,必須捕獲 StopIteration 錯誤,返回值包含在 StopIteration 的value中:

            
              g 
              
                =
              
               fib
              
                (
              
              
                6
              
              
                )
              
              
                while
              
              
                True
              
              
                :
              
              
                try
              
              
                :
              
              
        x 
              
                =
              
              
                next
              
              
                (
              
              g
              
                )
              
              
                print
              
              
                (
              
              
                'g:'
              
              
                ,
              
               x
              
                )
              
              
                except
              
               StopIteration 
              
                as
              
               e
              
                :
              
              
                print
              
              
                (
              
              
                'Generator return value:'
              
              
                ,
              
               e
              
                .
              
              value
              
                )
              
              
                break
              
            
          
            
              g: 1
g: 1
g: 2
g: 3
g: 5
g: 8
Generator return value: done

            
          

5.迭代器

我們已經知道,可以直接作用于 for循環 的數據類型有以下幾種:
一類是集合數據類型,如 list、tuple、dict、set、str 等;
一類是 generator ,包括 生成器 帶yield的generator function
這些可以直接作用于 for循環 的對象統稱為可迭代對象: Iterable
可以使用 isinstance() 判斷一個對象是否是 Iterable對象

            
              
                from
              
               collections 
              
                import
              
               Iterable

            
          
            
              
                # 判斷列表是不是可迭代對象
              
              
                isinstance
              
              
                (
              
              
                [
              
              
                ]
              
              
                ,
              
               Iterable
              
                )
              
            
          
            
              
                True
              
            
          
            
              
                # 判斷字典是不是可迭代對象
              
              
                isinstance
              
              
                (
              
              
                {
              
              
                }
              
              
                ,
              
               Iterable
              
                )
              
            
          
            
              
                True
              
            
          
            
              
                # 判斷字符串是不是可迭代對象
              
              
                isinstance
              
              
                (
              
              
                'abc'
              
              
                ,
              
               Iterable
              
                )
              
            
          
            
              
                True
              
            
          
            
              
                # 判斷一個生成器是不是可迭代對象
              
              
                isinstance
              
              
                (
              
              
                (
              
              x 
              
                for
              
               x 
              
                in
              
              
                range
              
              
                (
              
              
                10
              
              
                )
              
              
                )
              
              
                ,
              
               Iterable
              
                )
              
            
          
            
              
                True
              
            
          
            
              
                #判斷一個數是不是可迭代對象
              
              
                isinstance
              
              
                (
              
              
                100
              
              
                ,
              
               Iterable
              
                )
              
            
          
            
              
                False
              
            
          

而生成器不但可以作用于 for循環 ,還可以被 next()函數 不斷調用并返回下一個值,直到最后拋出 StopIteration 錯誤表示無法繼續返回下一個值了。
可以被 next()函數 調用并不斷返回下一個值的對象稱為迭代器: Iterator
可以使用 isinstance() 判斷一個對象是否是 Iterator 對象:

            
              
                # 判斷一個生成器是不是迭代器
              
              
                isinstance
              
              
                (
              
              
                (
              
              x 
              
                for
              
               x 
              
                in
              
              
                range
              
              
                (
              
              
                10
              
              
                )
              
              
                )
              
              
                ,
              
               Iterator
              
                )
              
            
          
            
              
                True
              
            
          
            
              
                # 判斷一個列表是不是迭代器
              
              
                isinstance
              
              
                (
              
              
                [
              
              
                ]
              
              
                ,
              
               Iterator
              
                )
              
            
          
            
              
                False
              
            
          
            
              
                # 判斷一個字典是不是迭代器
              
              
                isinstance
              
              
                (
              
              
                {
              
              
                }
              
              
                ,
              
               Iterator
              
                )
              
            
          
            
              
                False
              
            
          
            
              
                # 判斷一個字符串是不是迭代器
              
              
                isinstance
              
              
                (
              
              
                'abc'
              
              
                ,
              
               Iterator
              
                )
              
            
          
            
              
                False
              
            
          

生成器都是 Iterator 對象,但 list、dict、str 雖然是 Iterable ,卻不是 Iterator
list、dict、str Iterable 變成 Iterator 可以使用 iter() 函數:

            
              
                isinstance
              
              
                (
              
              
                iter
              
              
                (
              
              
                [
              
              
                ]
              
              
                )
              
              
                ,
              
               Iterator
              
                )
              
            
          
            
              
                True
              
            
          
            
              
                isinstance
              
              
                (
              
              
                iter
              
              
                (
              
              
                'abc'
              
              
                )
              
              
                ,
              
               Iterator
              
                )
              
            
          
            
              
                True
              
            
          

你可能會問,為什么 list、dict、str 等數據類型不是 Iterator
這是因為Python的 Iterator 對象表示的是一個數據流, Iterator 對象可以被 next() 函數調用并不斷返回下一個數據,直到沒有數據時拋出 StopIteration 錯誤。可以把這個數據流看做是一個有序序列,但我們卻不能提前知道序列的長度,只能不斷通過 next() 函數實現按需計算下一個數據,所以 Iterator 的計算是惰性的,只有在需要返回下一個數據時它才會計算。
Iterator 甚至可以表示一個無限大的數據流,例如全體自然數。而使用 list 是永遠不可能存儲全體自然數的。

小結

凡是可作用于 for循環 的對象都是 Iterable 類型;
凡是可作用于 next() 函數的對象都是 Iterator 類型,它們表示一個惰性計算的序列;
集合數據類型如 list、dict、str 等是 Iterable 但不是 Iterator ,不過可以通過 iter() 函數獲得一個 Iterator 對象。

Python的 for循環 本質上就是通過不斷調用 next() 函數實現的,例如:

            
              
                for
              
               x 
              
                in
              
              
                [
              
              
                1
              
              
                ,
              
              
                2
              
              
                ,
              
              
                3
              
              
                ,
              
              
                4
              
              
                ,
              
              
                5
              
              
                ]
              
              
                :
              
              
                pass
              
            
          

實際上完全等價于:

            
              
                # 首先獲得Iterator對象:
              
              
it 
              
                =
              
              
                iter
              
              
                (
              
              
                [
              
              
                1
              
              
                ,
              
              
                2
              
              
                ,
              
              
                3
              
              
                ,
              
              
                4
              
              
                ,
              
              
                5
              
              
                ]
              
              
                )
              
              
                # 循環:
              
              
                while
              
              
                True
              
              
                :
              
              
                try
              
              
                :
              
              
                # 獲得下一個值:
              
              
        x 
              
                =
              
              
                next
              
              
                (
              
              it
              
                )
              
              
                except
              
               StopIteration
              
                :
              
              
                # 遇到StopIteration就退出循環
              
              
                break
              
            
          

參考

https://www.liaoxuefeng.com/wiki/1016959663602400/1017323698112640


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

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

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

【本文對您有幫助就好】

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

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 伊人888| 青青草国产97免久久费观看 | 久久精品国产亚洲网站 | a v在线男人的天堂观看免费 | 午夜激情网站 | 国产网红自拍 | 天天插日日操 | 欧日韩美香蕉在线观看 | 日韩高清欧美精品亚洲 | 图片区亚洲 | 成 人 黄 色 大 片 | 最新欧美一级视频 | 91精品国产高清91久久久久久 | 欧美人交性视频在线香蕉 | 欧美高清成人 | 天天夜夜人人 | 四虎影视网 | 欧美激情亚洲精品日韩1区2区 | 国产区久久| 奇米线在人线免费视频 | 精品国产一区二区在线观看 | 深夜在线观看网站 | 国产午夜精品理论片久久影视 | 日韩伊人网 | 国产91精品一区二区麻豆网站 | 深夜在线免费视频 | 99精品国产兔费观看66 | 国产萝控精品福利视频免费 | 久久性生活视频 | 欧美一区二区日韩一区二区 | 亚洲特级毛片 | 夜夜操女人 | 亚洲欧美日韩在线不卡中文 | 操天天操 | 精品国产一二三区 | 国产精品视频公开费视频 | 99久久综合精品免费 | 一区二区三区四区在线视频 | 国产男女爱视频在线观看 | 欧美一级艳片爽快片 | bbw老妇bbwbbwass |