Python - 產生器:初學者的溫柔介紹
你好,有志成為 Python 程式設計師的人!今天,我們將進入 Python 產生器的精彩世界。如果你之前從未聽過它們,不必擔心 - 我們會從頭開始,逐步學習。在這個教程結束時,你將能像專家一樣創建產生器!
Python 產生器是什麼?
想象一下,你正在閱讀一本非常厚的書。你可以一次複印整本書(這將浪費很多紙張!),也可以一次讀一頁。這就是 Python 中產生器的工作原理!
產生器是一種特殊的函數,它允許我們隨著時間生成一系列值,而不是一次計算所有值並將它們存儲在記憶體中。它們就像魔法工廠一樣,按需生成值。
為什麼使用產生器?
- 記憶體效率:產生器對記憶體友好。它們不會一次將所有值存儲在記憶體中。
- 效能:它們可以改善你的代碼效能,尤其是處理大型數據集時。
- 簡潔:產生器可以使你的代碼更清晰、更易讀。
讓我們深入了解它們是如何工作的!
創建產生器
在 Python 中創建產生器主要有兩種方法:
- 使用產生器函數
- 使用產生器表達式
產生器函數
產生器函數看起來就像普通函數一樣,但使用 yield
關鍵字而不是 return
。以下是一個簡單的例子:
def count_up_to(n):
i = 1
while i <= n:
yield i
i += 1
# 使用我們的產生器
for number in count_up_to(5):
print(number)
輸出:
1
2
3
4
5
在這個例子中,count_up_to
是一個產生器函數。每次它產生一個值時,它都會暫停其執行並記住其狀態。下次調用它時,它會從上次離開的地方繼續。
產生器表達式
產生器表達式就像列表解析,但使用括號而不是方括號。它們是創建產生器的簡潔方式。以下是一個例子:
# 產生器表達式
squares = (x**2 for x in range(5))
# 使用我們的產生器
for square in squares:
print(square)
輸出:
0
1
4
9
16
這個產生器表達式即時創建一個平方數的序列,而不會一次將它們全部存儲在記憶體中。
產生器中的異常處理
產生器也可以處理異常,這非常酷!以下是一個例子:
def div_generator(a, b):
try:
result = a / b
yield result
except ZeroDivisionError:
yield "不能除以零!"
# 使用我們的產生器
g = div_generator(10, 2)
print(next(g)) # 輸出:5.0
g = div_generator(10, 0)
print(next(g)) # 輸出:不能除以零!
在這個例子中,我們的產生器在嘗試除以零時优雅地處理了情況。
普通函數與產生器函數
讓我們比較一個普通函數和一個產生器函數來看看差異:
# 普通函數
def get_squares(n):
squares = []
for i in range(n):
squares.append(i**2)
return squares
# 產生器函數
def gen_squares(n):
for i in range(n):
yield i**2
# 使用普通函數
print(get_squares(5)) # 輸出:[0, 1, 4, 9, 16]
# 使用產生器函數
for square in gen_squares(5):
print(square) # 每個平方數在新的一行上打印
主要差異在於:
- 記憶體使用:普通函數一次創建並存儲所有值,而產生器一次生成一個值。
- 語法:普通函數使用
return
,而產生器使用yield
。 - 迭代:可以 直接迭代產生器,而普通函數的結果需要先存儲在變量中。
非同步產生器
Python 3.6 引入了非同步產生器,它們就像普通產生器一樣,但用於非同步編程。它們使用 async def
和 yield
:
import asyncio
async def async_gen():
for i in range(3):
await asyncio.sleep(1)
yield i
async def main():
async for item in async_gen():
print(item)
asyncio.run(main())
這個例子模擬了一個隨時間產生值的非同步操作。
產生器方法
產生器有一些特殊的 方法可以非常有用。以下是最常見的一些:
方法 | 描述 |
---|---|
next() |
從產生器中检索下一個項目 |
send() |
將值傳入產生器 |
throw() |
在產生器中拋出異常 |
close() |
關閉產生器 |
以下是一個使用 send()
的快速示例:
def echo_generator():
while True:
received = yield
print(f"Received: {received}")
g = echo_generator()
next(g) # 創建產生器
g.send("Hello") # 輸出:Received: Hello
g.send("World") # 輸出:Received: World
就是這樣!你剛剛走出了 Python 產生器的精彩世界的第一步。記住,練習成就完美,所以不要害怕嘗試這些概念。在你意識到之前,你將會在 Python 程式中使用產生器來解決各種有趣的問題。編程愉快!
Credits: Image by storyset