10分鐘讀懂python生成器

在python中,生成器在項目中的使用頻率不可謂不高,可是對於剛接觸python的開發者來講,又是一個比較難懂的概念。本文將以一種簡單易懂的方式來解釋什麼是python生成器。python

列表生成式 vs 生成器

列表生成式和生成器常常被拿來作比較,一個比較直觀的對比是:bash

  • 列表生成式:[ ]是經過遍歷可迭代對象生成一個list函數

  • 生成器:( )是直接返回可迭代對象ui

舉個列表生成器的例子🌰:spa

[x+y for x in range(1,2) for y in range(1,3)] 
# result: [2,3,4,3,4,5]
複製代碼

經過外層[ ]包裹內層的循環,從range(1,2)列表和range(1,3)中分別取出x和y做相加操做,返回一個列表生成式,直接得到列表結果:[2,3,4,3,4,5]。這就是一個列表生成器。code

在這裏,咱們不妨讓range(1,2)提高几個量級到到range(1,20000),讓range(1,3)提高几個量級到到range(1,30000),再次計算結果就是一個容量爲20000*30000的列表,佔用了不少的存儲空間。假如咱們須要獲得列表的第1000個元素,那第1000個後面的元素就徹底不須要用到卻佔用空間,有點浪費。要是可以經過某種方式,不用計算所有的結果就能獲得結果,那該多好了。cdn

因而咱們的生成器登場了。協程

將上面的[ ]改成( )就是生成器了☑️:對象

g = (x+y for x in range(1,2) for y in range(1,3)])
for i in g:
    print (i)
複製代碼

咱們建立了一個名爲g的generator後,而是經過for循環來迭代打印它(其內部是經過不停調用next( )方法每次迭代出一個數據)開發

生成器函數

生成器函數和普通函數在語法上幾乎同樣,可是生成器函數多了個yield關鍵字。若是一個函數定義中包含yield關鍵字,那麼這個函數就再也不是一個普通函數,而是一個generator

def gen_list(n):
    for i in range(n):
      yield i ** 2
 
g = gen_list(4);
print(next(g));
print(next(g));
print(next(g));
# 結果
# 0
# 1
# 4
複製代碼

這裏經過yield語句一次返回一個結果並掛起當前狀態,下次調用的時候會從當前狀態繼續。經過這種方式,對延遲操做提供了支持。所謂延遲操做,是指在須要的時候才產生結果,而不是當即產生結果。就像這個例子中,咱們每次調用next,每次只獲得一個結果(依次是0、一、4...)

對比前面的經過列表生成式提升量級到range(1,20000)的例子來講,這裏的生成器由於一個一個結果計算,不須要計算所有列表,因此極大地節省了空間。同時,生成器使用經過yield狀態掛起該生成器函數的狀態,保留足夠的信息,以便以後從它離開的地方繼續執行,這就爲咱們以後文章會分析到的協程的實現提供了簡單的實現思路。

全棧公衆號,感興趣的小夥伴能夠關注下

你的全棧助手
相關文章
相關標籤/搜索