午夜视频在线网站,日韩视频精品在线,中文字幕精品一区二区三区在线,在线播放精品,1024你懂我懂的旧版人,欧美日韩一级黄色片,一区二区三区在线观看视频

分享

Python中iteration(迭代)、iterator(迭代器)、generator(生成器)等相關(guān)概念的理解

 宇哥小屋 2020-02-06

在閱讀Python tutorial類這一章的時(shí)候出現(xiàn)了iterator的概念,我是一個(gè)是編程的半吊子,雖然在其它語(yǔ)言(比如Java和C++)中也聽(tīng)過(guò)這個(gè)概念,但是一直沒(méi)認(rèn)真的去理解,這次我參考了一些文章,總結(jié)了一些我的看法。
首先,我在理解相關(guān)的概念的時(shí)候總是試圖探索引入相關(guān)概念的背后的真正意圖,我們看到的多半都是用法,那么為什么要這么用,也許搞清楚了每件事情背后的目的,接下來(lái)產(chǎn)生的解決方案才能順理成章水到渠成。那么這篇文章大多數(shù)是我通過(guò)現(xiàn)有的一些線索,推測(cè)出背后的一些可能的,也許我的理解充滿各種主觀因素,但是至少能夠自圓其說(shuō),也請(qǐng)各位能不吝賜教。其次,其中有些表述可能會(huì)有些啰嗦。

1. “迭代”這個(gè)概念引入主要是解決什么問(wèn)題的

首先你要知道什么叫做迭代

迭代就是單向地、逐個(gè)地訪問(wèn)某個(gè)容器中的元素的行為。 (可以理解為線性的方式訪問(wèn)容器中元素,單向、逐個(gè)是其特征)
在程序?qū)崿F(xiàn)中我們最常進(jìn)行的一種操作就是將容器(以下認(rèn)為“數(shù)據(jù)結(jié)構(gòu)”和“容器”是同義詞)里元素一個(gè)接一個(gè)的取出來(lái),但是為了實(shí)現(xiàn)這個(gè)簡(jiǎn)單的目的,針對(duì)不同的數(shù)據(jù)結(jié)構(gòu),我每次寫的代碼還都不一樣(這背后其實(shí)是要了解每個(gè)數(shù)據(jù)結(jié)構(gòu)的特性,并根據(jù)這些特性構(gòu)造合適的代碼),太麻煩了,于是我們想能不能這樣?能不能寫一個(gè)工具,每次我們需要在某個(gè)數(shù)據(jù)結(jié)構(gòu)上進(jìn)行迭代操作的時(shí)候,就調(diào)用這個(gè)工具,這個(gè)工具可以我們把不同數(shù)據(jù)結(jié)構(gòu)在方法實(shí)現(xiàn)細(xì)節(jié)上的不同屏蔽掉,這個(gè)工具就是迭代器,在python中是由類實(shí)現(xiàn)的。
迭代器是是一個(gè)抽象的概念,它代表了一種目的,而并非細(xì)節(jié)。所有實(shí)現(xiàn)了在某個(gè)特定數(shù)據(jù)結(jié)構(gòu)上進(jìn)行迭代行為的類都是迭代器。

延展概念

迭代是遍歷的一種特例,遍歷(traverse)是可以在數(shù)據(jù)結(jié)構(gòu)上來(lái)回的游走,不僅可以往前,還可以往后,同時(shí)還能保證不重不漏的,也就是把非線性的東西映射成線性的訪問(wèn)方式,而且還是不重不漏的,迭代是單向的而且只來(lái)一次。

2. 在這個(gè)程序語(yǔ)言中,這個(gè)概念是如何實(shí)現(xiàn)的

我們來(lái)看看這個(gè)東西在語(yǔ)言設(shè)計(jì)的層面是如何實(shí)現(xiàn)的:
我們假設(shè),在理想的情況下,如果有一個(gè)模塊或者一個(gè)函數(shù)里面實(shí)現(xiàn)了所有數(shù)據(jù)類型的迭代方式,假設(shè)這個(gè)模塊叫iterator,里面有一個(gè)方法叫做iteration,那么每次我用的時(shí)候,先import iterator,然后用iterator.iteration(帶迭代的變量)實(shí)現(xiàn)了一次迭代,這是比較理想的方式,但是現(xiàn)實(shí)中很難做到這點(diǎn),除了系統(tǒng)內(nèi)置的數(shù)據(jù)結(jié)構(gòu)之外,用戶自己實(shí)現(xiàn)的數(shù)據(jù)結(jié)構(gòu)咋辦,于是放棄這種大一統(tǒng)的思路,而把所有的實(shí)現(xiàn)都下放給用戶自己實(shí)現(xiàn)。在這種情況下,為了保證每個(gè)用戶寫的迭代器能夠被其它用戶使用,需要制定一些規(guī)范讓大家遵守,我斗膽把這個(gè)規(guī)范稱之為“迭代規(guī)范”吧,這個(gè)規(guī)范可以分成兩個(gè)層面來(lái)理解,一個(gè)是使用層面,一個(gè)是實(shí)現(xiàn)層面。

  • 首先我們來(lái)看使用層面,在python中迭代器的使用是這么一個(gè)套路:

    • 第一步,由待迭代的容器變量創(chuàng)建一個(gè)對(duì)應(yīng)的迭代器。
      在python中,有一個(gè)內(nèi)置的函數(shù)iter(),這個(gè)函數(shù)以待迭代的容器變量為參數(shù),創(chuàng)建出對(duì)應(yīng)于這種容器的迭代器。
    • 第二步,調(diào)用迭代器的next方法,每一次調(diào)用next方法只會(huì)得到一個(gè)元素。
      在python中,迭代器里面有一個(gè)next()方法,我們可以直接調(diào)用這個(gè)方法,但是常用的方法是利用python的內(nèi)置函數(shù)next(),這個(gè)函數(shù)以迭代器為參數(shù),相當(dāng)于調(diào)用了迭代器的next()方法,簡(jiǎn)單一點(diǎn)。
  • 然后是實(shí)現(xiàn)層面,也分成兩步:

    • 第一步,我稱之為“數(shù)據(jù)的可迭代聲明”(或者叫做“可迭代實(shí)現(xiàn)”)
      你必須要證明你的數(shù)據(jù)結(jié)構(gòu)是可迭代(iteratable)的,從觀念上或者數(shù)學(xué)上看你的數(shù)據(jù)結(jié)構(gòu)里的數(shù)據(jù)必須是有限可列或者至少是可列的(可列的概念其實(shí)是有理數(shù)或者無(wú)理數(shù)中用到的概念)。只有數(shù)據(jù)結(jié)構(gòu)可迭代,才有為這個(gè)數(shù)據(jù)結(jié)構(gòu)構(gòu)造迭代器的意義。在具體的實(shí)現(xiàn)層面,一個(gè)可迭代的數(shù)據(jù)結(jié)構(gòu)要滿足下面的要求(這個(gè)數(shù)據(jù)結(jié)構(gòu)一般來(lái)說(shuō)是一個(gè)類),必須實(shí)現(xiàn)iter方法,這個(gè)方法需要返回一個(gè)迭代器。
    • 第二步,叫做“迭代器的實(shí)現(xiàn)”
      實(shí)現(xiàn)iterator需要實(shí)現(xiàn)兩個(gè)方法,這兩個(gè)方法一起被稱之為迭代器協(xié)議(iterator protocol)。
      • 第一個(gè)方法是iter,這個(gè)方法返回的是實(shí)現(xiàn)迭代器的這個(gè)類自身,你會(huì)奇怪,實(shí)現(xiàn)了iter方法的不是說(shuō)明這個(gè)類是可迭代的嗎?是的,迭代器一般來(lái)說(shuō)也是可迭代的。
      • 第二個(gè)方法是next方法,這個(gè)方法返回的是容器中的下個(gè)元素,如果沒(méi)有更多的元素了,則會(huì)raise一個(gè)StopIteration異常。

迭代器協(xié)議的要點(diǎn)和難點(diǎn)在next方法的實(shí)現(xiàn)上(這為生成器的引入埋下了伏筆),而在next方法的實(shí)現(xiàn)有三個(gè)要點(diǎn),其中最難的一點(diǎn)在于理解“數(shù)據(jù)現(xiàn)用現(xiàn)生成”或者說(shuō)“用到某個(gè)元素的時(shí)候才把它生成(計(jì)算)出來(lái)”的思想。
這里就要引入另一個(gè)問(wèn)題了,我斗膽把它稱之為“數(shù)據(jù)的準(zhǔn)備問(wèn)題”。
啥意思呢?比方說(shuō)在程序中,在用一個(gè)數(shù)據(jù)之前我們首先得“有”一個(gè)數(shù)據(jù),那么我們?nèi)绾巍坝小币粋€(gè)數(shù)據(jù)?
兩種方法,一種方式是我把所有可能要用到元素都生成出來(lái)并且全部保存在內(nèi)存中然后再在使用的過(guò)程中去拿我要用的元素;還有一種是我用某個(gè)元素的前一刻時(shí)才去生成元素,然后再去用。你會(huì)覺(jué)得,我靠這還算一個(gè)問(wèn)題么,必須后一種啊,前一種明顯是在浪費(fèi)空間么(參考firstn的例子)。很不幸的時(shí)候,在python2有很多底層的數(shù)據(jù)實(shí)現(xiàn)就是沒(méi)有效率,你單看他們的時(shí)候都沒(méi)有問(wèn)題,但是一旦代碼的規(guī)模變大,層層調(diào)用之后就不好說(shuō)了。好,我們統(tǒng)一觀點(diǎn)之后,再討論下一個(gè)問(wèn)題。
在使用數(shù)據(jù)的前一刻把數(shù)據(jù)生成可能嗎?
其實(shí)是可能的,這也分兩種可能,一種可能是我們要自己“憑空創(chuàng)造”數(shù)據(jù),其實(shí)說(shuō)“憑空創(chuàng)造”其實(shí)不準(zhǔn)確,因?yàn)楸举|(zhì)上任何可列的數(shù)據(jù)都是自然數(shù)的函數(shù)(這個(gè)函數(shù)是數(shù)學(xué)意義上的函數(shù)),只要有函數(shù)(映射法則)以及自變量,求出因變量不是很簡(jiǎn)單的事情嗎?還有一種可能就是數(shù)據(jù)原來(lái)就存在了(比如說(shuō)存在數(shù)據(jù)庫(kù)里或者文件里),我們只需要取出來(lái)就可以,那么在這種情況下我們只要獲取保存數(shù)據(jù)的位置信息就能獲取到實(shí)際的數(shù)據(jù)值了,其實(shí)也可以理解為建立自然數(shù)和位置信息的映射。理解了這點(diǎn),另外兩個(gè)實(shí)現(xiàn)細(xì)節(jié)就好說(shuō)了,比如我們經(jīng)常會(huì)用(不是絕對(duì))一個(gè)游標(biāo)來(lái)記錄位置信息,可能這個(gè)游標(biāo)是一個(gè)計(jì)數(shù)器,然后我們利用循環(huán)的方式讓其自增從而實(shí)現(xiàn)迭代特性中的“單向”,“逐個(gè)”特征。再有就是最后一定要返回StopIteration。小結(jié)一下next方法的要點(diǎn)就是:
1. 數(shù)據(jù)現(xiàn)用現(xiàn)生成
2. 單向,逐個(gè)特性的實(shí)現(xiàn)
3. 最后返回StopIteration

在語(yǔ)法上,返回StopIteration比其它兩點(diǎn)都重要,next方法啥也不做,直接返回StopIteration都行。例如下面這個(gè)例子

>>> class Simplest_Iterator(object):
...     def next(self): # Python 2 compatibility
...         return self.__next__()
...     def __next__(self):
...         raise StopIteration
...
>>> z = Simplest_Iterator()
>>> next(z)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 5, in __next__
StopIteration

值得注意的是,依據(jù)在“數(shù)據(jù)的可迭代聲明”這一步中iter方法返回的容器對(duì)象是自身還是其它對(duì)象的不同,迭代器在使用上會(huì)表現(xiàn)出不同的特性。
1. iter方法返回的是容器對(duì)象本身。這種實(shí)現(xiàn)方式叫做“容器本身既是迭代器”,這種情況迭代器構(gòu)造出來(lái)之后只能使用一次。
2. iter方法返回的是其他的對(duì)象。這種實(shí)現(xiàn)方式叫做“數(shù)據(jù)和迭代器的分離”,其實(shí)這個(gè)更像是工具的思想,我第一次閱讀與迭代器實(shí)現(xiàn)相關(guān)的文檔時(shí)腦海里首先想到是這種方法。

那么這兩種方式有什么區(qū)別呢?在Python中,大多數(shù)容器類型(哪些屬于容器類型,參考這篇文章)都是采用第二種方式實(shí)現(xiàn)的,都是采用“數(shù)據(jù)和迭代器分離”的實(shí)現(xiàn)的方式的,這是因?yàn)椤翱傻逼鋵?shí)從觀念上意味著,我在這個(gè)種容器上反復(fù)進(jìn)行迭代的,如果“容器本身即是迭代器”的話,每次容器每次調(diào)用iter方法返回的是自身,在經(jīng)過(guò)一次迭代之后,游標(biāo)指到容器最后一個(gè)元素后面,同時(shí)拋出了異常,迭代器就再也無(wú)法工作了,除非你利用一些方法把next方法中的游標(biāo)置為初始狀態(tài)。而我們采用數(shù)據(jù)和迭代器分離的方式話,每次容器調(diào)用iter方法的時(shí)候,都會(huì)重新生成一個(gè)新的迭代器對(duì)象,這樣就可以無(wú)限次的在容器上進(jìn)行迭代了。

數(shù)據(jù)和迭代器分離的實(shí)現(xiàn)方式示意圖

數(shù)據(jù)即使迭代器的實(shí)現(xiàn)方式示意圖

下面用例子來(lái)說(shuō)明,我們實(shí)現(xiàn)一個(gè)與內(nèi)置函數(shù)xrange的類似的類
實(shí)現(xiàn)方式1:“容器本身即是迭代器”

class yrange:
    def __init__(self, n):
        self.i = 0
        self.n = n

    def __iter__(self):
        return self

    def __next__(self):
        if self.i < self.n:
            i = self.i
            self.i += 1
            return i
        else:
            raise StopIteration()

之后我們來(lái)做一下測(cè)試:

>>> y = yrange(3)
>>> y.next()
0
>>> y.next()
1
>>> y.next()
2
>>> y.next()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 14, in next
StopIteration

實(shí)現(xiàn)方式2. 數(shù)據(jù)和迭代器的分離的例子:

class zrange:
    def __init__(self, n):
        self.n = n

    def __iter__(self):
        return zrange_iter(self.n)

class zrange_iter:
    def __init__(self, n):
        self.i = 0
        self.n = n

    def __iter__(self):
        # Iterators are iterables too.
        # Adding this functions to make them so.
        return self

    def __next__(self):
        if self.i < self.n:
            i = self.i
            self.i += 1
            return i
        else:
            raise StopIteration()

然后我們比較一下兩個(gè)類的不同

>>> y = yrange(5)
>>> list(y)
[0, 1, 2, 3, 4]
>>> list(y)
[]
>>> z = zrange(5)
>>> list(z)
[0, 1, 2, 3, 4]
>>> list(z)
[0, 1, 2, 3, 4]

3. 這些概念有什么用?

  1. 毫無(wú)疑問(wèn)第一個(gè)應(yīng)用就是做遍歷
    學(xué)過(guò)數(shù)據(jù)結(jié)構(gòu)的都知道所有操作的基礎(chǔ)都是基于遍歷,如果解決了遍歷的問(wèn)題,就等于說(shuō)解決了一大半的問(wèn)題
    甚至文件都可以進(jìn)行迭代哦

  2. 可以用來(lái)生成數(shù)據(jù)(我估計(jì)生成器的名字就是這樣來(lái)的吧)
    在迭代器實(shí)現(xiàn)的核心思想就是“數(shù)據(jù)用到的時(shí)候才生成”,那么我們是不是可以用這個(gè)方式來(lái)生成數(shù)據(jù)?而且這種實(shí)現(xiàn)方式意外的節(jié)省空間?這點(diǎn)正好引入下一個(gè)要討論的知識(shí)點(diǎn),也就是生成器
    最有說(shuō)服力的是那個(gè)斐波那契數(shù)列的例子

4. 生成器

簡(jiǎn)單來(lái)說(shuō),生成器就是迭代器實(shí)現(xiàn)的簡(jiǎn)化。相比用一個(gè)實(shí)現(xiàn)迭代器協(xié)議的類來(lái)實(shí)現(xiàn)迭代器而言,我們只要定義一個(gè)函數(shù)就可以實(shí)現(xiàn)迭代器,這個(gè)函數(shù)就是生成器。
那么這個(gè)函數(shù)如何定義呢?我們以yrange迭代器為例,生成器實(shí)現(xiàn)如下:

def yrange(n):
    i = 0
    while i < n:
        yield i
        i += 1

怎么理解這個(gè)代碼,有很多人說(shuō)這個(gè)東西簡(jiǎn)單,但是我不這么覺(jué)得,其實(shí)越是看似簡(jiǎn)單的東西里面越是有深刻的知識(shí)在里面。就像我在next方法實(shí)現(xiàn)那部分中對(duì)“在使用數(shù)據(jù)的前一刻把數(shù)據(jù)生成可能嗎?”這個(gè)問(wèn)題進(jìn)行的討論一樣,對(duì)于數(shù)據(jù)的生成,除了在已經(jīng)存儲(chǔ)數(shù)據(jù)的地方進(jìn)行獲取以外,還有一種方式是“把它計(jì)算出來(lái)”,而計(jì)算的方法,本質(zhì)上是建立一個(gè)從自然數(shù)序列到我們所要的序列的一個(gè)映射。對(duì)于后一種方式來(lái)說(shuō),我們要做的事情就是,遍歷自然數(shù)序列,對(duì)于每個(gè)自然數(shù),把它作為映射法則的因變量放入到映射法則中去進(jìn)行運(yùn)算,把運(yùn)算出來(lái)的結(jié)果返回出去。比如映射關(guān)系是f(x),那么這個(gè)代碼可以這么寫:

def generatorexample(n):
    i = 0
    while i < n:
        yield f(i)
        i += 1

也就說(shuō)把計(jì)算的結(jié)果(在程序中就是一個(gè)表達(dá)式)返回出去的那步用yield關(guān)鍵字來(lái)返回就行了。

那么這個(gè)背后實(shí)現(xiàn)機(jī)制是怎么樣的,
1. 當(dāng)generator function被調(diào)用的時(shí)候,這個(gè)函數(shù)會(huì)返回一個(gè)generator對(duì)象之后什么都不做。
2. 當(dāng)next方法被調(diào)用的時(shí)候,函數(shù)就會(huì)開(kāi)始執(zhí)行直到y(tǒng)ield所在的位置,計(jì)算出來(lái)的值在這個(gè)位置被返回,之后這個(gè)函數(shù)就停下了。之后再調(diào)用next方法的時(shí)候,函數(shù)繼續(xù)執(zhí)行,直到遇到下一個(gè)yield。
3. 如果執(zhí)行完的代碼,還沒(méi)有遇到y(tǒng)ield,就會(huì)拋出StopIteration異常。

>>> def foo():
...     print "begin"
...     for i in range(3):
...         print "before yield", i
...         yield i
...         print "after yield", i
...     print "end"
...
>>> f = foo()
>>> f.next()
begin
before yield 0
0
>>> f.next()
after yield 0
before yield 1
1
>>> f.next()
after yield 1
before yield 2
2
>>> f.next()
after yield 2
end
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration
>>>

再比如:

def my_generator():
    print("return first value")
    yield 1
    print("return second value")
    yield 2
    print("return last value")
    yield 3
    print("raise StopIteration")

z = my_generator()
next(z)
next(z)
next(z)
next(z)

這里面有一些地方一下說(shuō)明一下,其實(shí)如果深究起“generator”來(lái),其實(shí)這還是一個(gè)非常模糊的詞呢,generator到底是說(shuō)那個(gè)函數(shù)呢?還是說(shuō)這個(gè)函數(shù)返回的值呢?
在官方的glossary里面,generator就指得是那個(gè)包含yield語(yǔ)句的函數(shù)體,也就是“generator function”,而這個(gè)如果要指代這個(gè)函數(shù)返回的對(duì)象,一般稱之為“generator iterator”,官方建議為了避免歧義,最好把詞說(shuō)全一點(diǎn)。
而我還是喜歡這篇文章的描述,“generator function ”就是那個(gè)函數(shù)體,“generator”表示“generator function”這個(gè)函數(shù)返回的對(duì)象。

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

生成器表達(dá)式可以看成迭代器在生成器的基礎(chǔ)上進(jìn)一步簡(jiǎn)化(還能在懶一點(diǎn)嗎),用好理解的話說(shuō)就是——生成器表達(dá)式可以看成列表推導(dǎo)式的生成器版。列表推導(dǎo)是可以看我的另一篇文章
雖所簡(jiǎn)化了形式,但是我感覺(jué)更接近迭代器的本質(zhì)了——也就是“構(gòu)造一個(gè)和自然數(shù)序列一一對(duì)應(yīng)的序列”

6. 總結(jié)一下這幾個(gè)概念的關(guān)系

借用一張圖
這里寫圖片描述

7.迭代思想在Python中的廣泛存在

在tutorial里面有這么一句話The use of iterators pervades and unifies Python.
基本上來(lái)說(shuō)迭代的思想在Python這門語(yǔ)言的實(shí)現(xiàn)過(guò)程中已經(jīng)滲透在各個(gè)角落,已經(jīng)是底層的設(shè)計(jì)思想了,很多語(yǔ)法都是基于迭代這個(gè)概念向上建造的。以下是一些例子

  1. 很多容器類型都是iterable
    甚至文件類型都是可以用for語(yǔ)句來(lái)訪問(wèn)的。我們最常用的一個(gè)數(shù)據(jù)結(jié)構(gòu)list,它是用iterable作為參數(shù)來(lái)初始化一個(gè)list,其實(shí)執(zhí)行了這樣的初始化函數(shù)

    class list(object):
    ...
    def __init__(self, iterable):
        for i in iterable:
            self.value.append(i)
    ...
  2. 很多函數(shù)的參數(shù)以及返回值都是iterable
    map(), filter() ,zip() ,range()
    dict.keys(), dict.items() 和 dict.values()

  3. for其實(shí)也是語(yǔ)法糖
    基于迭代的語(yǔ)法糖
    比如:

    for i in iterable:
    func(i)

    本質(zhì)上是:

    z = iter(iterable)
    try:
    while True:
        func(next(z))
    except StopIteration:
    pass
  4. unpack也是語(yǔ)法糖
    比如:

    >>> a,b = b,a # 等價(jià)于 a,b = (b,a)
    >>> a,b,*_ = [1,2.3,4] # 僅適用于 Python 3
    >>> a,b,*_ = iter([1,2.3,4]) # 也可以用于迭代器
    >>> a
    1
    >>> b
    2.3
    >>> _
    [4]

    其實(shí)是賦值是這么實(shí)現(xiàn)的:

    k = iter(iterable)
    a = next(k)
    b = next(k)
    _ = list(k)
  5. list comperhension也是語(yǔ)法糖
    上面雖然說(shuō)generator experssion是生成器版本的list comperhension,這只是為了便于理解,其實(shí)先后順序應(yīng)該顛倒過(guò)來(lái)。
    List Comprehension 也只是語(yǔ)法糖而已,甚至還可以寫出 tuple/set/dict comprehension(其實(shí) set 就是所有 key 的 value 都為 None 的 dict)

    >>> [x*x for x in range(10)]
    [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
    >>> list(x*x for x in range(10))
    [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
    >>> tuple(x*x for x in range(10))
    (0, 1, 4, 9, 16, 25, 36, 49, 64, 81)
    >>> set(x*x for x in range(10))
    {0, 1, 64, 4, 36, 9, 16, 49, 81, 25}
    >>> dict((x,x*x) for x in range(10))
    {0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81}

參考文獻(xiàn)

  1. Python Practice Book 我的不少例子都引自這個(gè)
  2. 官網(wǎng)wiki對(duì)于iterator的解釋 官方的迭代器的解釋 Q&A 不錯(cuò) 說(shuō)明了iter方法和next方法的不一定非要是一個(gè) 鏈接里的IBM鏈接失效了,但是搜索一下就行了
  3. 官網(wǎng)wiki對(duì)于generator的解釋 節(jié)省空間的例子不錯(cuò)
  4. 官方文檔對(duì)于iterator protocol的解釋
  5. Python 筆記(3):可迭代變量 后面的好多語(yǔ)法糖的例子都來(lái)自這篇文章,感謝這位作者,PS:你的博客里的那個(gè)背景音也是我喜歡的,很想和你交個(gè)朋友呢,可是你沒(méi)寫聯(lián)系方式
  6. python迭代器與生成器小結(jié) 這篇文章值得一看
  7. Iterables vs. Iterators vs. Generators 引用率也很高的文章,我引用了其中一張圖片,根據(jù)我的理解修改了一些圖片
  8. Python yield 使用淺析斐波那契數(shù)列的例子 仔細(xì)看了一下這個(gè)居然是廖雪峰寫的

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多