Python生成器和迭代器

一、什麼是生成器python

要說生成器,那就要先看列表,有了列表爲啥還要生產器呢。列表能夠寫成解析式,書寫簡單,運行速度快,可是列表是一次性生成所有數據,若是數據較大就須要很大的內存。shell

>>> a=[i*i for i in range(10)]
>> a
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

列表a須要一次把所有數據生成出來,若是數據成千上萬就會受限制。數組

若是列表元素不是一次性所有生成,而是在循環中不斷的計算推導出來,那就不須要一次建立列表數組,不須要申請很大的內存空間,這就是生成器。函數

二、生成器的特色spa

上面的列表推導式的方括號改成圓括號,就是生成器。code

>>> a=(i*i for i in range(10))
>>> a
<generator object <genexpr> at 0x00000224FFB4DB48>

那麼怎麼從生成器裏取數據呢?對象

>>> next(a)
0
>>> next(a)
1
>>> next(a)
4
>>> next(a)
9
>>> next(a)
16
>>> next(a)
25

生成器generator有一個next方法,每次調用都會計算出他的下一個元素的值。生成器是能夠迭代的,因此能夠直接使用for語句循環生成器。blog

>>> a=[i*i for i in range(10)]
>>> for i in a:
    print(i, end=' ')    
>>> 0 1 4 9 16 25 36 49 64 81

除了使用圓括號建立生成器,也能夠用yeild建立生成器,含有yeild關鍵字的函數都是生成器。生成器實際上是一種特殊的迭代器,可是不須要像迭代器同樣實現__iter__和__next__方法,只須要使用關鍵字yield就能夠。索引

def gen_squares(num):
    for x in range(num):
        print("x0=",x)
        yield x ** 2
        print("x1=",x)

調用生成器:內存

for i in gen_squares(5):
    print(i)

輸出以下,開始x=0,先輸出x0=0,而後yeild返回print(i)打印平方數。下次循環回到yeild位置執行輸出x1=1,而後循環x=1,輸出x0=1,再次yeild到print(i)。

x0= 0
0
x1= 0
x0= 1
1
x1= 1
x0= 2
4
x1= 2
x0= 3
9
x1= 3
x0= 4
16
x1= 4

調用部分作個簡單修改:

for i in gen_squares(5):
    print(i)
    if i==1:
        break

輸出爲以下,可見yield能保存內部狀態,並掛起中斷退出。在下一輪迭代調用時,從yield的地方繼續執行,而且沿用上一輪的函數內部變量的狀態,直到內部循環過程結束。

x0= 0
0
x1= 0
x0= 1
1

python使用生成器對延遲操做提供了支持,須要時才計算,不提早計算,這種作法節約內存空間,可是須要一直調用計算過程,能夠說是時間換空間吧。

三、什麼是迭代器

實現了__iter__和__next__方法的對象都稱爲迭代器。迭代器完成迭代功能,基於上一次的結果重複計算,自動記錄所在的位置,而不須要手動記錄索引,含有__iter__方法的對象都是可迭代對象。

迭代對象內置兩個方法:__next__和__iter__方法。next方法可使迭代器自動記錄迭代位置而不須要用戶維護索引。iter方法能返回迭代器自己。

迭代器是一個有狀態的對象,在調用next() 的時候返回下一個值,若是容器中沒有更多元素了,則拋出StopIteration異常。

列表、元組就實現了迭代器。

>>> a=[1,2,3,4]
>>> it = a.__iter__()
>>> next(it)
1
>>> next(it)
2
>>> next(it)
3
>>> next(it)
4
>>> next(it)
Traceback (most recent call last):
  File "<pyshell#547>", line 1, in <module>
    next(it)
StopIteration

四、實現迭代對象

class square:
    def __init__(self, n):
        self.prev = 0
        self.curr = 0
        self.n = n

    def __iter__(self):
        return self

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

a
= square(10) for i in a: print(i) print("\r\n-------\r\n") b = square(5) for i in b: print(i)

輸出結果爲:

==================== RESTART: C:/Users/plu/my_python/t1.py ====================
0
1
4
9
16
25
36
49
64
81
 
------- 

0
1
4
9
16
>>>
相關文章
相關標籤/搜索