Python 列表生成式和生成器?可迭代和迭代器?

Python 列表生成式和生成器?可迭代和迭代器?

列表生成式和生成器?

列表生成式,就是一個能夠生成列表的推導式,用[]括起來,裏面是一個包含for循環的推導式,形式一般如下:

[x * x for x in range(1, 11) if x % 2 == 0]

意思是從1-10遍歷,選取偶數數字然後平方組成新的列表。

生成器,generator,兩種寫法,第一種把上面的列表生成式的中括號[]改成小括號(),如下:

g = (x * x for x in range(10))

需要注意這樣得到的不是一個列表也不是元組,也不是1-10每個數平方後的數據,而是一個生成器對象,它又麼用呢?

使用列表生成式是一下子把所有元素都計算出來,比如說我們最終要100萬個元素,列表生成式一下子計算就得到了100萬個元素,但是就目前而言我只用到前10個後面的元素以後纔可能用,那一下子計算出100萬個又慢有佔空間。

所以生成器就可以按需計算,即我們只需要告訴它計算推導的規則就行,想要得到下一個元素,我們就調用next()方法按照規則計算獲取下一個元素,當然也可以用for循環獲取前n個元素,所以它有一種惰性計算的性質。

比如上面代碼中的生成器,可以使用next()方法不斷獲取下一個元素:

g = (x * x for x in range(10))
next(g) # 0
next(g) # 1
next(g) # 4

也可以使用for循環:

g = (x * x for x in range(10))
for n in g:
	print(n)
# 0
# 1
# 4
# 9
...
# 81

第二種方式就是通過函數告訴它計算規則,但是函數畢竟是函數,怎麼變成生成器呢,只要每次計算出數據用yield關鍵字返回就行了,比如計算斐波那契數量:

def fib(max):
    n, a, b = 0, 0, 1
    while n < max:
        yield b # 計算出b並返回,下次執行從上次終止的地方開始而不是重新開始
        a, b = b, a + b
        n = n + 1
    return 'done'

也是可以通過next()或者for循環去遍歷,比如使用next()方法:

g = fib(6) # 創建一個生成6個斐波那契數的生成器
next(g)
# 1
next(g)
# 1
next(g)
# 2
next(g)
# 3
next(g)
# 5
next(g)
# 8
next(g)
# Traceback (most recent call last):
#  File "<stdin>", line 1, in <module>
#  StopIteration

發現每次執行next()方法,它是從上次停止的地方繼續執行,而不會像函數一樣從頭開始,最後結束如果繼續調用next()方法會返回StopIteration異常。

使用for循環同理:

for n in fib(6):
	print(n)
# 1
# 1
# 2
# 3
# 5
# 8

可迭代和迭代器?

可以直接作用於for循環的數據類型有以下幾種:

一類是集合數據類型,如listtupledictsetstr等;

一類是generator,包括生成器和帶yield的generator function。

凡是可作用於for循環的對象都是可迭代的,叫Iterable類型;

凡是可作用於next()函數的對象都是迭代器,叫Iterator類型,它們表示一個惰性計算的序列;

集合數據類型如listdictstr等是Iterable但不是Iterator,不過可以通過iter()函數獲得一個Iterator對象。

Python的Iterator對象也就是迭代器,表示的是一個數據流,Iterator對象可以被next()函數調用並不斷返回下一個數據,直到沒有數據時拋出StopIteration錯誤。可以把這個數據流看做是一個有序序列,但我們卻不能提前知道序列的長度,只能不斷通過next()函數實現按需計算下一個數據,所以Iterator的計算是惰性的,只有在需要返回下一個數據時它纔會計算。

Iterator甚至可以表示一個無限大的數據流,例如全體自然數。而使用list是永遠不可能存儲全體自然數的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章