Python中產生器和迭代器的區別__Python

來源:互聯網
上載者:User
Python中產生器和迭代器的區別(代碼在Python3.5下測試): Num01–>迭代器 定義:

對於list、string、tuple、dict等這些容器物件,使用for迴圈遍曆是很方便的。在後台for語句對容器物件調用iter()函數。iter()是python內建函數。
iter()函數會返回一個定義了next()方法的迭代器對象,它在容器中逐個訪問容器內的元素。next()也是python內建函數。在沒有後續元素時,next()會拋出一個StopIteration異常,通知for語句迴圈結束。

迭代器是用來協助我們記錄每次迭代訪問到的位置,當我們對迭代器使用next()函數的時候,迭代器會向我們返回它所記錄位置的下一個位置的資料。實際上,在使用next()函數的時候,調用的就是迭代器對象的_next_方法(Python3中是對象的_next_方法,Python2中是對象的next()方法)。所以,我們要想構造一個迭代器,就要實現它的_next_方法。但這還不夠,python要求迭代器本身也是可迭代的,所以我們還要為迭代器實現_iter_方法,而_iter_方法要返回一個迭代器,迭代器自身正是一個迭代器,所以迭代器的_iter_方法返回自身self即可。 一些術語的解釋:

1,迭代器協議:對象需要提供next()方法,它要麼返回迭代中的下一項,要麼就引起一個StopIteration異常,以終止迭代。

2,可迭代對象:實現了迭代器協議對象。list、tuple、dict都是Iterable(可迭代對象),但不是Iterator(迭代器對象)。但可以使用內建函數iter(),把這些都變成Iterable(可迭代器對象)。

3,for item in Iterable 迴圈的本質就是先通過iter()函數擷取可迭代對象Iterable的迭代器,然後對擷取到的迭代器不斷調用next()方法來擷取下一個值並將其賦值給item,當遇到StopIteration的異常後迴圈結束 Python內建容器物件案例:

# 隨便定義一個listlistArray=[1,2,3]# 使用iter()函數iterName=iter(listArray)print(iterName)# 結果如下:是一個列表list的迭代器# <list_iterator object at 0x0000017B0D984278>print(next(iterName))print(next(iterName))print(next(iterName))print(next(iterName))#沒有迭代到下一個元素,直接拋出異常# 1# 2# 3# Traceback (most recent call last):#   File "Test07.py", line 32, in <module># StopIteration
Python中一個實現了_iter_方法和_next_方法的類對象,就是迭代器,如下案例是計算菲波那切數列的案例
class Fib(object):    def __init__(self, max):        super(Fib, self).__init__()        self.max = max    def __iter__(self):        self.a = 0        self.b = 1        return self    def __next__(self):        fib = self.a        if fib > self.max:            raise StopIteration        self.a, self.b = self.b, self.a + self.b        return fib# 定義一個main函數,迴圈遍曆每一個菲波那切數def main():    # 20以內的數    fib = Fib(20)    for i in fib:        print(i)# 測試if __name__ == '__main__':    main()

解釋說明:

在本類的實現中,定義了一個_iter_(self)方法,這個方法是在for迴圈遍曆時被iter()調用,返回一個迭代器。因為在遍曆的時候,是直接調用的python內建函數iter(),由iter()通過調用_iter_(self)獲得對象的迭代器。有了迭代器,就可以逐個遍曆元素了。而逐個遍曆的時候,也是使用內建的next()函數通過調用對象的_next_(self)方法對迭代器對象進行遍曆。所以要實現_iter_(self)和_next_(self)這兩個方法。

而且因為實現了_next_(self)方法,所以在實現_iter_(self)的時候,直接返回self就可以。

總結一句話就是:
在迴圈遍曆自訂容器物件時,會使用python內建函數iter()調用遍曆對象的_iter_(self)獲得一個迭代器,之後再迴圈對這個迭代器使用next()調用迭代器對象的_next_(self)。

注意點:_iter_(self)只會被調用一次,而_next_(self)會被調用 n 次,直到出現StopIteration異常。 Num02–>產生器 作用:

>延遲操作。也就是在需要的時候才產生結果,不是立即產生結果。
注意事項:
>產生器是只能遍曆一次的。>產生器是一類特殊的迭代器。
分類:

第一類:產生器函數:還是使用 def 定義函數,但是,使用yield而不是return語句返回結果。yield語句一次返回一個結果,在每個結果中間,掛起函數的狀態,以便下次從它離開的地方繼續執行。

如下案例加以說明:

# 菲波那切數列def Fib(max):    n, a, b = 0, 0, 1    while n < max:        yield b        a, b = b, a + b        n = n + 1    return '親。沒有資料了...'# 調用方法,產生出10個數來f=Fib(10)# 使用一個迴圈捕獲最後return 返回的值,儲存在異常StopIteration的value中while  True:    try:        x=next(f)        print("f:",x)    except StopIteration as e:        print("產生器最後的傳回值是:",e.value)        break

第二類:產生器運算式:類似於列表推導,只不過是把一對大括弧[]變換為一對小括弧()。但是,產生器運算式是按需產生一個產生器結果對象,要想拿到每一個元素,就需要迴圈遍曆。

如下案例加以說明:

# 一個列表xiaoke=[2,3,4,5]# 產生器generator,類似於list,但是是把[]改為()gen=(a for a  in xiaoke)for  i  in gen:    print(i)#結果是:2345# 為什麼要使用產生器。因為效率。# 使用產生器運算式取代列表推導式可以同時節省 cpu 和 記憶體(RAM)。# 如果你構造一個列表(list)的目的僅僅是傳遞給別的函數,# 比如 傳遞給tuple()或者set(), 那就用產生器運算式替代吧!# 本案例是直接把列錶轉化為元組kk=tuple(a for a in xiaoke)print(kk)#結果是:(2, 3, 4, 5)# python內建的一些函數,可以識別這是產生器運算式,外面有一對小括弧,就是產生器result1=sum(a for a in range(3))print(result1)# 列表推導式result2=sum([a for a in range(3)])print(result2)
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.