溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何理解Python的容器、可迭代對象、迭代器、生成器

發(fā)布時間:2021-10-12 10:09:52 來源:億速云 閱讀:140 作者:iii 欄目:開發(fā)技術(shù)

本篇內(nèi)容主要講解“如何理解Python的容器、可迭代對象、迭代器、生成器”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“如何理解Python的容器、可迭代對象、迭代器、生成器”吧!

目錄
  • 一、容器

    • 1.什么是容器?

  • 二、可迭代對象

    • 1.什么是可迭代對象?

  • 三、迭代器

    • 四、序列

      • 五、列表推導式

        • 六、生成器

          • 1.生成器的第一種創(chuàng)建方法:生成器表達式

          • 2.生成器的第二種創(chuàng)建方法:yield

        如何理解Python的容器、可迭代對象、迭代器、生成器

        一、容器

        1.什么是容器?

        在Python中,容器是把多種元素組織在一起的數(shù)據(jù)結(jié)構(gòu),容器中的元素就可以逐個迭代獲取。說白了,它的作用就像它的名字一樣:用來存放東西(數(shù)據(jù))。

        容器實際上是不存在的,它并不是一種數(shù)據(jù)類型,只是人為的一種概念,只是為了方便學習所創(chuàng)造的一個概念詞,它可以用成員關(guān)系操作符(in或not in)來判斷對象是否在容器里面。

        當然了,它不是我創(chuàng)造的,我沒有那么大本事哈,是官方創(chuàng)造的好吧,你也不用擔心我是在教你一些奇奇怪怪的名詞,說出去別人都聽不懂…python中都是這么叫的。

        如何理解Python的容器、可迭代對象、迭代器、生成器

        常見的容器類型有列表(list)、元組(tuple)、字符串(str)、字典(dict)以及集合(set )。

        既然容器里面的數(shù)據(jù)是可以迭代獲取的,那么我們又得來學一個新概念:可迭代對象。

        二、可迭代對象

        1.什么是可迭代對象?

        在python中,可迭代對象并不是指某種具體的數(shù)據(jù)類型,它是指存儲了元素的一個容器對象。

        也就是說,如果容器里面沒有存儲數(shù)據(jù),那它就不是可迭代對象,并不是所有的容器都是可迭代對象,容器包含但并不僅限于可迭代對象。

        注意兩個點:

        • 1.很多容器都是可迭代對象(容器包含了可迭代對象)。

        • 2.一個可迭代對象是不能獨立的進行迭代的,迭代是通過for來完成的,凡是可迭代對象都可以直接使用for循環(huán)進行訪問。

        for循環(huán)大家應該不陌生吧?有沒有想過,for循環(huán)內(nèi)部是怎么實現(xiàn)的?比如說這個for循環(huán)的例子,為什么能輸出列表里的每一個元素?它的內(nèi)部是怎么實現(xiàn)的?

        如何理解Python的容器、可迭代對象、迭代器、生成器

        其實for循環(huán)做了兩件事情:

        • 1.使用 __iter__() 返回1個迭代器,迭代器在下面會講,這里先知道有這么個東西。

        • 2.使用 __next__() 獲取迭代器中的每一個元素。

        那么我們不用for循環(huán)來輸出列表里的每一個元素,

        l = [1,2,3,4]
        # for i in l:
        #     print(i)
        ite =l.__iter__() #接收一下ietr()干了什么
        print(ite)  #打印
        print(ite.__next__())    #for循環(huán)干第2件事情的時候做的第1步
        print(ite.__next__())    #for循環(huán)干第2件事情的時候做的第2步
        print(ite.__next__())    #for循環(huán)干第2件事情的時候做的第3步
        print(ite.__next__())    #for循環(huán)干第2件事情的時候做的第4步

        輸出結(jié)果:

        如何理解Python的容器、可迭代對象、迭代器、生成器

        可以看出來,如果我們?nèi)サ裟男写蛴te的代碼,執(zhí)行效果就是跟for循環(huán)輸出列表里面的每一個元素是一樣的,for循環(huán)里面限定了范圍是4次,實際上就執(zhí)行了1次__iter__()和4次__next__(),也就是說for循環(huán)訪問迭代對象的本質(zhì)就是通過這么去實現(xiàn)的。

        而且,for循環(huán)本質(zhì)上干的那兩件事情,缺一不可,也就是說如果沒有__iter__()先返回了迭代器,__next()__也無法獲取到元素,恰恰說明了前面說要注意的兩點中的第2點:一個可迭代對象是不能獨立的進行迭代的。

        有兩個內(nèi)置函數(shù)跟它們原理是一樣的,本質(zhì)相同,一般要用的話用內(nèi)置函數(shù)要方便一些,起碼不用寫那么多下劃線:

        • 內(nèi)置函數(shù) iter() 的本質(zhì)是 __inter__() ,也是返回一個迭代器。

        • 內(nèi)置函數(shù) next() 的本質(zhì)是 __next__(),也是有了迭代器之后獲取元素。

        如何理解Python的容器、可迭代對象、迭代器、生成器

        可以看出來結(jié)果也是一模一樣的,既然講到了迭代器,那么就來看看什么是迭代器。

        如何理解Python的容器、可迭代對象、迭代器、生成器

        三、迭代器

        通過上面的for循環(huán)例子我們大概也能看得出來,

        • 只要是實現(xiàn)了__iter__()和__next__()的對象,就是迭代器,迭代器是一個可迭代對象。

        • 總之,迭代器是有__iter__()生成,可以通過__next__()進行調(diào)用。

        既然如此,我們在學Python基礎(chǔ)的時候講過range()是一個可迭代對象,那么它也是可以通過__iter__()生成一個迭代器的。

        如何理解Python的容器、可迭代對象、迭代器、生成器

        四、序列

        序列在【賦值語句】那個專題文章中我有提過,這里再講一下,序列也是一個抽象的概念,它包含了列表、元組和字符串,它本身是不存在的,也是便于學習所創(chuàng)造的一個概念詞。

        可迭代對象包含序列,既然序列包含了列表、元組和字符串,前面我們的例子中也涉及到 了,所以說序列可以被iter()和next()使用。

        序列可以分為有限序列和無限序列。有限序列就是有范圍的,比如說range(10)就已經(jīng)限定了范圍,相反的,無限序列也就是沒有限定范圍的序列。

        我們來生成一個無限序列,這里需要用到1個新模塊itertools,itertools用于高效循環(huán)的迭代函數(shù)集合,它下面有一個方法count(),可生成迭代器且無范圍,可以理解為無限迭代器。

        如何理解Python的容器、可迭代對象、迭代器、生成器

        通過這個例子我們可以看出來,只要執(zhí)行一次,next()就會獲取一次迭代器里面的內(nèi)容并逐次獲取,我這里只寫了4個next(),你多寫幾次就會多輸出幾次。

        像next()這種什么時候需要就什么時候調(diào)用的機制叫做懶加載機制,也叫懶漢式加載;

        相反地就有餓漢式加載。比如for循環(huán)這種的,只要一執(zhí)行就會把可迭代器里面的所有對象都獲取。

        五、列表推導式

        列表推導式跟生成器有關(guān),在講生成器之前,需要先知道什么是列表推導式,列表推導式就是生成列表的一種方法,語法是這樣的:

        l = [i for i in 可迭代對象]

        i表示要放進列表里的對象,for循環(huán)是一個式子。

        比如我們用列表推導式來生成一個列表試試:

        l = [i for i in range(5)]
        print(l)

        運行結(jié)果:

        [0, 1, 2, 3, 4]

        運用列表推導式可以很方便地生成我們想要的列表。

        同時它也有很多靈活的用法,比如在后面加上條件判斷

        l = [i for i in range(5) if 4<5]
        print(l)

        運行結(jié)果:

        [0, 1, 2, 3, 4]

        if后面的條件判斷為真,則可以正常生成列表,如果為假,則列表推導式是無效的,此時的l將是一個空列表。

        還有其他靈活的用法,比如操作前面的i,比如讓i的數(shù)值全都翻2倍:

        如何理解Python的容器、可迭代對象、迭代器、生成器

        我們把迭代對象換一下,換成字符串,也同樣可以輸出,只是*在字符串里面表示重復操作符,所以效果變成了這樣:

        如何理解Python的容器、可迭代對象、迭代器、生成器

        不僅如此,前面的i*2我們還可以用函數(shù)來進行操作,比如:

        如何理解Python的容器、可迭代對象、迭代器、生成器

        總而言之,列表推導式就是用來快速和自定義生成列表的一種方法,很靈活。

        那么有人可能會舉一反三了,列表推導式都是用 [] 來進行操作的,那如果用()來操作行嗎?它會不會生成一個元組?我們來看看:

        如何理解Python的容器、可迭代對象、迭代器、生成器

        [] 換成()之后,返回的是一個生成器generrator ,那么下面我們再來講講生成器:

        六、生成器

        生成器是真實存在于Python中的對象,與容器這種概念詞是不同的,它是可以直接通過next()進行調(diào)用的。

        1.生成器的第一種創(chuàng)建方法:生成器表達式

        第一種創(chuàng)建方法跟列表推導式是差不多的,就是 [] 換成了():

        l = (i for i in 可迭代對象)

        比如我們來生成一個生成器,看看能不能用next()直接調(diào)用:

        l = (i for i in "abcd")
        print(next(l))

        運行結(jié)果:

        a

        可以看出,生成器是可以直接調(diào)用的。那么既然生成器可以被next()調(diào)用,那么生成器就是一個特殊的迭代器,是一個可迭代對象。

        2.生成器的第二種創(chuàng)建方法:yield

        除了用上面那種方法創(chuàng)建生成器,還可以用yield來創(chuàng)建,方法如下:

        yield 關(guān)鍵字

        比如說我們用一個函數(shù)中包含yield來創(chuàng)建生成器:

        def fun():
            a = 10
            while 1:
                a += 1
                yield a
        
        
        b = fun()
        print(b)

        運行結(jié)果:

        <generator object fun at 0x000001F2AD95E900>

        結(jié)果就是生成了一個生成器,而且此時的函數(shù)fun()就已經(jīng)不再是一個函數(shù)了,它是一個生成器,只要函數(shù)中出現(xiàn)了yield,函數(shù)就變成了生成器。

        為什么while循環(huán)沒有一直執(zhí)行?先不著急,我們輸出看看:

        def fun():
            a = 10
            while 1:
                a += 1
                yield a
        
        
        b = fun()
        print(next(b))
        print(next(b))
        print(next(b))

        運行結(jié)果:

        11
        12
        13

        我調(diào)用了三次,所以它就運行了三次,while循環(huán)雖然存在,但是卻不起作用,是因為前面我們提過的懶漢式加載。

        什么時候需要了,什么時候用next()調(diào)用,就是懶漢式加載,不像餓漢式加載那樣,提前生成了所有對象,如果這里換成for循環(huán)來完成,比如:

        def fun():
            a = 10
            while 1:
                a += 1
                print(a)
        
        b = fun()

        運行之后程序?qū)M入死循環(huán),一直給a自加1,你可以試試看效果,這就是餓漢式加載提前生成了迭代器并調(diào)用了全部迭代器對象,餓漢式加載占用資源的放大鏡。

        如何理解Python的容器、可迭代對象、迭代器、生成器

        七、小結(jié)

        今天講的內(nèi)容可能聽起來比較枯燥,這也是沒得辦法的,有些東西第一次聽可能有點”難以下咽“,見得多了之后就習慣了,你得強迫自己去試著接受和理解這些抽象的東西。

        最后用一張圖來總結(jié)一下它們的關(guān)系:

        如何理解Python的容器、可迭代對象、迭代器、生成器

        到此,相信大家對“如何理解Python的容器、可迭代對象、迭代器、生成器”有了更深的了解,不妨來實際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進入相關(guān)頻道進行查詢,關(guān)注我們,繼續(xù)學習!

        向AI問一下細節(jié)

        免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

        AI