1. 程式人生 > >python 迭代器和生成器的區別

python 迭代器和生成器的區別

迭代器(iterator)是一個實現了迭代器協議的物件,python的一些內建資料型別(列表,陣列,字串,字典等)都可以通過for語句進行迭代,我們也可以自己建立一個容器,實現了迭代器協議,可以通過for,next方法進行迭代,在迭代的末尾,會引發stopIteration異常。


In [14]: it = range(2)

In [15]: ite = iter(it)

In [16]: ite.next()
Out[16]: 0

In [17]: ite.next()
Out[17]: 1

In [18]: ite.next()
---------------------------------------------------------------------------
StopIteration                             Traceback (most recent call
last) <ipython-input-18-887aa41fdfa0> in <module>() ----> 1 ite.next() StopIteration:

自己實現及使用迭代器:為容器物件新增iter(),_next()方法,在呼叫時,可以通過next以及for迴圈

class PythonLearn:
    def __init__(self, start = 0, stop = 0):
        self.start = start
        self.stop = stop

    def __iter__(self):
print('call __iter__') return self def next(self): print("call __next__") if self.start < self.stop: i = self.start self.start += 1 return i else: raise StopIteration if __name__ == '__main__': learn = PythonLearn(2
,5) next(learn) print(next(learn)) for i in learn: print i

執行結果:

call __next__
call __next__
3
call __iter__
call __next__
4
call __next__

生成器(generator)是通過yield語句快速生成迭代器,可以不用iter和next方法
yield可以使一個普通函式變成一個生成器,並且相應的next()方法返回是yield後的值。一種更直觀的解釋是:程式執行到yield時會返回結果並暫停,再次呼叫next時會從上次暫停的地方繼續開始執行。
顯然,生成器自身有構成一個迭代器,每次迭代時使用一個yield返回 的值,一個生成器中可以有多個yield的值

In [21]: def test():
   ....:     yield 1
   ....:     yield 3
   ....:     yield 22
   ....:

In [22]: a = test()

In [23]: type(a)
Out[23]: generator

In [24]: a.next()
Out[24]: 1

In [25]: a.next()
Out[25]: 3

In [26]: a.next()
Out[26]: 22

xrange 和range的區別

In [9]: xrange(5)
Out[9]: xrange(5)

In [10]: range(5)
Out[10]: [0, 1, 2, 3, 4]

In [11]: list(xrange(5))
Out[11]: [0, 1, 2, 3, 4]

In [12]: print type(xrange(4))
<type 'xrange'>

In [13]: print type(range(4))
<type 'list'>

range(1000)會返回一個長度為1000的陣列,而xrange(1000)會返回一個生成器,在需要的情況下返回一個數字,此時空間的佔用情況會大為減少。所以為了提升效能,在做迴圈的時候,應該儘可能的使用xrange,除非需要用range返回一個數組。