Python next() 方法 – 最優雅的迭代器使用法

在使用 Python 時,會出現這樣的情況:

「我只想從列表中精確提取符合條件的第一個項目,該怎麼做?」

這時最 Pythonic 和優雅的方法就是 next()。其實,之所以寫這篇文章,也正是因為每當使用 next() 提取列表中的所需項目時,總會不禁感嘆,「哇,這真的是太優雅了……」。因此,它也是我個人非常喜愛的代碼之一。對於像我這樣喜歡 Django 和 DRF 的朋友來說,也是必備的代碼。
為什麼這個方法在 Django 中有用,稍後會詳述。

這就是 next(),雖小卻非常強大的工具。用法不難,但對於從未使用過的人來說,可能會感到陌生,所以這篇文章會非常詳細地為大家講解。


next() 的本質:請求迭代器的下一個值的函數

next() iterator flow diagram

首先讓我們抓住這個概念。

next(iterator[, default])
  • iterator:可以從可迭代對象中調用 .next() 的迭代器。
  • default:當迭代結束時要返回的預設值,而不是 StopIteration 異常。
  • 返回值:從迭代器中提取下一個值。

例子:

it = iter([1, 2, 3])
print(next(it))  # 1
print(next(it))  # 2
print(next(it))  # 3
print(next(it))  # 觸發 StopIteration 異常

防止異常:

print(next(it, '結束'))  # 返回預設值 → '結束'

好吧,理解到這裡,您應該知道 next() 是一個將迭代器逐步推進的工具。然而光這一點可能還無法讓您真切感受到在實際中的用途,接下來我會展現其真正的魅力。


實戰範例 – 從列表中提取符合條件的第一項

users = [
    {'id': 1, 'name': 'Alice'},
    {'id': 2, 'name': 'Bob'},
    {'id': 3, 'name': 'Charlie'},
]

user = next((u for u in users if u['id'] == 2), None)
print(user)  # {'id': 2, 'name': 'Bob'}

當我第一次接觸這個語句時,印象非常深刻。它的簡潔與優雅無與倫比。使用 for 循環時需要 4~5 行代碼,而這樣一行就能解決。而且這不僅是因為簡短,而是因為它清楚地表達了意圖,在這方面優越許多。

這種方法的優點是什麼?

  • 一行中包含了條件和搜索。
  • 當沒有結果時返回 None,更安全。
  • 比使用 for 循環更簡潔(但內部實際上執行了相同的迭代過程)。

這個語句特別能讓初學者感到「哇,這種表達也行?」的驚訝,而對於中級用戶則會覺得「這必須列入我的技術庫」。


dict.get() 的對比 – 簡單鍵搜索 vs 條件搜索

my_dict = {'name': 'Alice', 'age': 30}
my_dict.get('age')       # 30
my_dict.get('city', '沒有')  # '沒有'

如上所示,dict.get()鍵確定的情況下非常有用。然而,next() 則發揮作用於列表中的字典,當需要根據條件尋找特定項目時。

user = next((u for u in users if u['name'].startswith('C')), None)

這樣可以找到 name 以 C 開頭的第一個用戶。這是 .get() 絕對無法實現的基於條件的訪問。


Django 和 next() – 使用頻繁

在 Django 中,QuerySet 是可迭代的,但是延遲評估。因此,必須首先使用 list() 強制進行評估。之後,進行條件搜索時 next() 非常有用。

qs = list(MyModel.objects.filter(active=True))
item = next((obj for obj in qs if obj.name == '洪吉童'), None)

這種方法在以下情況下非常有用: - 用 filter() 已經足夠過濾,但最終條件複雜或動態。 - 當有無法用 .first() 處理的自定義條件時。 - 想在不使用循環的情況下迅速提取單個項目時。

實際上,我在從事 Django 開發時,經常處理一些無法用 .first() 捕獲的條件。閱讀代碼的同事們也能快速理解這種表達,對於協作也很有幫助。


使用提示摘要

  • next((x for x in iterable if 條件), None) 形式記牢在腦中
  • 因為可能沒有返回值,所以養成一個習慣,務必設置 default 值。
  • 記住 dict.get() 是鍵搜索,next() 是條件搜索。
  • 可用於所有可迭代對象。
  • 不要過度使用 – 過於複雜的條件,還是使用 for 循環會更明顯。

結語 – 讓代碼變得美麗的小工具

next() 看起來像是一個簡單的函數,但它蘊含了 Python 的迭代器哲學,是一個非常強大的工具。尤其是在想從列表中提取符合條件的第一個項目時,幾乎找不到比這更直觀和簡潔的表達。

希望透過這篇文章,您也能有「啊,我也想用那段代碼」的想法,那麼您已經半隻腳踏進了這個領域。接下來只需多加練習幾次,讓它成為您的第二天性。

未來我還會不定期介紹簡單而美妙的 Python 代碼。 😊