python 迭代器和生成器的區別
阿新 • • 發佈:2019-02-14
迭代器(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返回一個數組。