Python - 迭代器

大家好,有志於成為 Python 程式設計師的你!今天,我們將進入 Python 迭代器的奇妙世界。身為你親切友善的電腦科學老師,我非常高興能引導你們通過這個迷人的主題。所以,拿起你 最喜歡的飲料,放鬆身心,讓我們一起深入探討!

Python - Iterators

Python 迭代器

迭代器是什麼?

想象一下,你有一個裝滿彩色樂高積木的大盒子。迭代器就像一隻神奇的手,可以伸進盒子中一次拿出 一塊樂高積木,讓你可以逐一檢查每塊積木,而不需要把整盒的東西倒在地板上。在 Python 中, 迭代器的工作方式類似,讓我們可以一次處理一個數據集合中的項目。

迭代器如何工作?

Python 的迭代器是實現了兩個特殊方法的對象:__iter__()__next__()。如果這些對你來說 看起來像胡言亂語,先別擔心——我們將一步一步來解釋!

  1. __iter__() 方法返回迭代器對象本身。這就像在說,“嘿,我準備好要開始發樂高積木了!"
  2. __next__() 方法返回序列中的下一個項目。這就像伸手進盒子,拿出下一塊樂高積木。

讓我們透過一個簡單的例子來看看這是怎麼工作的:

# 創建一個列表(我們的樂高積木盒)
my_list = [1, 2, 3, 4, 5]

# 從列表中獲取迭代器
my_iterator = iter(my_list)

# 使用 next() 一次獲取一個項目
print(next(my_iterator))  # 輸出:1
print(next(my_iterator))  # 輸出:2
print(next(my_iterator))  # 輸出:3

在這個例子中,iter(my_list) 為我們的列表創建了一個迭代器對象。然後,每次調用 next(my_iterator) 從列表中检索下一個項目。

迭代器在循環中的威力

這裡有一個有趣的事實:當你在 Python 中使用 for 循環時,其實你是在幕後使用迭代器!讓我們看看是怎麼回事:

my_list = ["apple", "banana", "cherry"]

for fruit in my_list:
print(f"I love {fruit}!")

# 輸出:
# I love apple!
# I love banana!
# I love cherry!

Python 自動從 my_list 創建一個迭代器,並使用 __next__() 從循環中獲取每個項目。這不 是很棒嗎?

迭代器的錯誤處理

那麼,當我們的神奇樂高積木检索手伸進一個空盒子時會發生什麼?在 Python 的語境中,當迭代器中沒有更多的項目時會發生什麼?這就是錯誤處理進場的時候。

當迭代器耗盡(沒有更多的項目)時,它會引發一個 StopIteration 例外。讓我們看看這是怎麼工作的:

my_list = [1, 2, 3]
my_iterator = iter(my_list)

print(next(my_iterator))  # 輸出:1
print(next(my_iterator))  # 輸出:2
print(next(my_iterator))  # 輸出:3
print(next(my_iterator))  # 引發 StopIteration 例外

為了妥善處理這一情況,我們可以使用 try-except 區塊:

my_list = [1, 2, 3]
my_iterator = iter(my_list)

try:
while True:
item = next(my_iterator)
print(item)
except StopIteration:
print("達到迭代器結尾!")

# 輸出:
# 1
# 2
# 3
# 達到迭代器結尾!

這樣,我們可以平滑地處理所有項目並妥善處理迭代器的結尾。

自定义迭代器

現在我們已經了解了迭代器是如何工作的,讓我們來創建自己的迭代器!想象我們想要創建一個倒數計時迭代器。以下是我們可以如何做到這一點:

class Countdown:
def __init__(self, start):
self.start = start

def __iter__(self):
return self

def __next__(self):
if self.start <= 0:
raise StopIteration
self.start -= 1
return self.start + 1

# 使用我們的自定义迭代器
countdown = Countdown(5)
for number in countdown:
print(number)

# 輸出:
# 5
# 4
# 3
# 2
# 1

在這個例子中,我們創建了一個 Countdown 類,它既是一個可迭代的(它有一個 __iter__() 方法) 也是一個迭代器(它有一個 __next__() 方法)。每次調用 __next__() 時,它都會返回倒數序列中的下一個數字。

异步迭代器

當我們進入更先進的領域時,讓我們簡短地談談異步迭代器。這些用於異步編程,是一種編寫並發代碼的方法。

異步迭代器與普通迭代器類似,但它使用 asyncawait 關鍵字。以下是一個簡單的例子:

import asyncio

class AsyncCountdown:
def __init__(self, start):
self.start = start

def __aiter__(self):
return self

async def __anext__(self):
await asyncio.sleep(1)  # 模拟一些異步操作
if self.start <= 0:
raise StopAsyncIteration
self.start -= 1
return self.start + 1

async def main():
async for number in AsyncCountdown(5):
print(number)

asyncio.run(main())

# 輸出(帶有 1 秒延時):
# 5
# 4
# 3
# 2
# 1

這個異步迭代器的工作方式與我們之前的 Countdown 類類似,但它允許異步操作(在這裡用 asyncio.sleep(1) 模拟)。

迭代器方法表格

以下是總結我們討論過的關鍵方法的便捷表格:

方法 描述 用於
__iter__() 返回迭代器對象 常規迭代器
__next__() 返回序列中的下一個項目 常規迭代器
__aiter__() 返回異步迭代器對象 異步迭代器
__anext__() 返回異步序列中的下一個項目 異步迭代器

就是這樣,各位!我們已經穿越了 Python 迭代器的領域,從基礎到創建自己的迭代器,甚至還接觸了異步迭代器。記住,就像學習建造樂高一樣,掌握迭代器需要練習。所以,不要害怕實驗並建造你自己的迭代器。編程愉快,願迭代器與你同在!

Credits: Image by storyset