python 迭代器和產生器用法詳解

來源:互聯網
上載者:User

python 迭代器

迭代器是一個實現了迭代器協議的對象,Python中的迭代器協議就是有next方法的對象會前進到下一結果,而在一系列結果的末尾是,則會引發StopIteration。

>>> l = range(2)
>>> i = iter(l)
>>> i
<listiterator object at 0x10a38d990>
>>> i.next()
0
>>> i.next()
1
>>> i.next()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

在for迴圈中,Python將自動調用工廠函數iter()獲得迭代器,自動調用next()擷取元素,還完成了檢查StopIteration異常的工作。

# 當發生StopIteration異常,退出迴圈
for a in range(2):
    print a

常用的幾個內建資料結構tuple、list、set、dict都支援迭代器,字串也可以使用迭代操作。

你也可以自己實現一個迭代器,如上所述,只需要在類的iter方法中返回一個對象,這個對象擁有一個next()方法,這個方法能在恰當的時候拋出StopIteration異常即可。但是需要自己實現迭代器的時候不多,即使需要,使用產生器會更輕鬆。

#!/usr/bin/env python
# coding=utf-8

class test:
    def __init__(self, input_list):
        self.list = input_list
        self.i = 0

    def __iter__(self):
        return self
   
    def next(self):
        if self.i == len(self.list):
            self.i = 0
            raise StopIteration
        self.i += 1
        return  self.list[self.i - 1]
使用迭代器一個顯而易見的好處就是:每次只從對象中讀取一條資料,不會造成記憶體的過大開銷。

例如:

/* 把檔案一次載入到記憶體中,然後逐行列印。當檔案很大時,這個方法的記憶體開銷就很大了 */
for line in open("test.txt").readlines():
    print line

/* 這是最簡單也是運行速度最快的寫法,他並沒顯式的讀取檔案,而是利用迭代器每次讀取下一行 */
for line in open("test.txt"):   #use file iterators
    print line
產生器
產生器的編寫方法和函數定義類似,只是在return的地方改為yield。

產生器中可以有多個yield。當產生器遇到一個yield時,會暫停運行產生器,返回yield後面的值。當再次調用產生器的時候,會從剛才暫停地方繼續運行,直到下一個yield。

產生器自身又構成一個迭代器,每次迭代時使用一個yield返回的值。


>>> def gen():
...     yield 1
...     yield 2
...
>>> a = gen()
>>> a.next()
1
>>> a.next()
2
>>> a.next()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration
>>>
需要注意的是,產生器中不需要return語句,不需要指定傳回值,在產生器中已經存在預設的返回語句

產生器運算式

(i for i in range(5))
// 返回迭代器
<generator object <genexpr> at 0x7ff3e8f0d960>
列表解析,返回list


[i for i in range(5)]
// 返回list
[0, 1, 2, 3, 4]

在這裡存在一個問題,那就是range(5)會返回一個長度為5的資料,如果是range(1000)那麼就會佔用一個1000大小的數組空間;如果我們採用產生器,在需要的時候產生一個數字,那麼空間的佔用情況就會降低,這裡我們可以使用xrange()函數來實現。


xrange
    函數說明:用法與range完全相同,所不同的是產生的不是一個數組,而是一個產生器。
xrange樣本:

>>> xrange(5)
xrange(5)
>>> list(xrange(5))
[0, 1, 2, 3, 4]
>>> xrange(1,5)
xrange(1, 5)
>>> list(xrange(1,5))
[1, 2, 3, 4]
>>> xrange(0,6,2)
xrange(0, 6, 2)
>>> list(xrange(0,6,2))
[0, 2, 4]
所以xrange做迴圈的效能比range好,尤其是返回很大的時候,盡量用xrange吧,除非你是要返回一個列表

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.