Python筆記003 生成器和生成器表示式

2021-09-24 09:19:08 字數 3358 閱讀 8282

以下是我學習《流暢的python》後的個人筆記,現在拿出來和大家共享,希望能幫到各位python學習者。

生成器使用yield做關鍵字,一次只返回乙個值給呼叫者,然後暫停執行,其作用是:節省記憶體空間。

生成器可以用next()函式,也可以用for迭代的方式獲取元素值,中間還可以用close()來隨時終止生成器。

生成器表示式可以認為是一種特殊的生成器,其**更簡潔,更容易理解,且和別的函式結合會更加靈活。

生成器是python中乙個特殊的程式,用於控制迴圈的迭代行為。相對於一般函式用return來一次性返回所有值,生成器使用yield關鍵字,一次只返回乙個值。

這樣的設計有很大的好處:在資料處理時,如果函式return出來的是乙個非常大的陣列,那麼會非常占用記憶體,有時會報memoryerror的錯誤,而使用yield後一次僅僅返回乙個元素值,可以優化記憶體占用的情況。

從這種角度來講,生成器函式每一次呼叫都返回乙個元素值,這種特性使得生成器長得像函式,但行為卻像迭代器。

def

squares

(x):

# 計算0-x的所有數的平方

# return [i*i for i in range(x)] # 普通寫法,一次返回乙個list,包含所有元素

for i in range(x):

yield i*i # 生成器:一次只返回乙個值

print(squares(5)) #

# 獲取生成器中的元素值

for value in squares(5): # 行為類似於迭代器,迴圈獲取元素值

print('value: ',value)

複製**

生成器並不像一般的函式,它返回乙個值後,生成器函式會自動掛起,等到下一次呼叫時(使用其內部成員方法__next__來實現),再返回到這個函式中繼續執行。

所以要想獲取生成器的元素值,需要通過成員方法next()來進行,比如:

square_five=squares(5)

print(next(square_five)) # 0

print(next(square_five)) # 1

print(next(square_five)) # 4

print(next(square_five)) # 9

print(next(square_five)) # 16

print(next(square_five)) # 報錯:stopiteration: 超過yield的所有元素

複製**

next()函式每次執行時,都會繼續執行掛起的生成器函式,直到執行完畢。

生成器的這種特點被稱為"延遲計算"或"惰性求值(lazy evaluation)",可以有效的節省記憶體。惰性求值實際上是體現了協同程式的思想。

雖然生成器的這種行為類似於迭代器,但兩者有較大差別,迭代器不具備這種執行-暫停-再執行-再暫停的特性,所以迭代器不具有延遲計算,沒有協同程式的思想。

使用延遲計算後,可以極大的節省記憶體,比如對大檔案進行讀取操作時,可以用下列生成器方法:

## 讀取大檔案的生成器方法:

defload_big_file

(file_path):

block_size = 1024

with open(file_path, 'rb') as f:

while

true:

block = f.read(block_size)

if block:

yield block # 一次只載入乙個block到記憶體中,避免memoryerror

else:

return

複製**

生成器除了用next()函式來處理之外,還可以用close()來隨時退出生成器。如下**:

## 使用close()可以隨時退出生成器

square_five=squares(5)

print(next(square_five)) # 0

print(next(square_five)) # 1

print(next(square_five)) # 4

square_five.close() # 退出生成器

print(next(square_five)) # error: stopiteration:

print(next(square_five)) # error: stopiteration:

複製**

從形式上來看,生成器表示式和列表推導式很像,僅僅是將列表推導式中的替換為(),但是兩者差別挺大,生成器表示式可以說組合了迭代功能和列表解析功能。

生成器表示式可以認為是一種特殊的生成器函式,類似於lambda表示式和普通函式。但是和生成器一樣,生成器表示式也是返回生成器generator物件,一次只返回乙個值。

# 上面的squares函式可以改寫為:

# 列表推導式的寫法是:

squares_list=[i*i for i in range(5)] # 一次性返回整個list

print('列表推導式:',squares_list) # 列表推導式: [0, 1, 4, 9, 16]

# 生成器表示式:

squares2=(i*i for i in range(5)) # 生成器表示式一次返回乙個值

print('生成器表示式:',squares2) # 生成器表示式: print(next(squares2)) # 0

print(next(squares2)) # 1

print(next(squares2)) # 4

複製**

生成器表示式是一種特殊的生成器,所以它也有生成器的特性,可以使用for迴圈來獲取元素值,for迴圈內部自動呼叫了next()函式來執行。

# generator物件可以直接用for來獲取所有元素值

squares2=(i*i for i in range(5)) # 生成器表示式就是乙個generator物件

for i in squares2:

print('i: ',i)

# 上面可以簡寫為:

[print('i: ',i) for i in (i*i for i in range(5))]

複製**

生成器表示式如果作為某個函式的引數,則可以省略掉(),直接使用即可,eg:

## 如果生成器表示式整個作為某個函式的引數,可以省略掉()

max_value=max(i*i for i in range(5)) # 計算生成器的所有元素中的最大值

print(max_value) # 16

複製**

003 生成器 迭代器

現在有個需求,列表 1,2,3,4,5,6,7,8,9 將列表裡的每個值加1。a 1,2,3,4,5,6,7,8,9 b for item in a a b print a a 1,2,3,4,5,6,7,8,9 for index,ele in enumerate a,0 a index 1 pr...

python3生成器 Python3 生成器

python3 生成器 閱讀 125 發布於 2020 05 19 14 29 25 在python中,一邊迴圈一邊計算出元素的機制,稱為生成器 generator。生成器的優點 一次返回乙個結果,延遲計算。這對於大資料量處理,是個非常有用的優勢。占用記憶體量是工程師必須考慮的乙個問題。提高 可讀性...

Python(九)生成器

該系列文章用來記錄一下自己在b站學習python時,進行上機練習用的 使用 pycharm 2020.3.3 慕課 python語言基礎與應用 北京大學 陳斌 字幕校對 編寫程式,輸入兩個數,輸出它們的商,採用例外處理來處理兩種錯誤,給出使用者友好的提示資訊 1 除數為0 2 輸入了非數值 try ...