生成器和迭代器的區別在于生成器是特殊的迭代器通過yield實現無需手動編寫__next__()方法。1.迭代器是實現__iter__()和__next__()方法的對象如list、dict、str需調用iter()才能成為迭代器。2.生成器通過函數中的yield自動生成__next__()邏輯每次調用next()會從上次yield處繼續執行。3.yield的作用是暫停函數并保存狀態實現惰性求值節省內存適合處理大數據流。4.yield與return不同return直接結束函數而yield返回值后保留函數狀態后續可繼續執行。5.使用yield from可嵌套生成器多個yield之間可插入其他邏輯如網絡請求或狀態檢查。
生成器和迭代器是 python 中非常實用但容易讓人混淆的概念,尤其是 yield 這個關鍵字,很多人剛接觸時都會有點懵。簡單來說,yield 是用來創建生成器的,而生成器是一種特殊的迭代器,可以按需產生值,節省內存。
什么是迭代器(Iterator)?
迭代器是實現了 __iter__() 和 __next__() 方法的對象。你可以把它理解成一個“能一步步取值的東西”。比如我們常用的 list、dict、str 都是可迭代對象,但它們本身不是迭代器,需要調用 iter() 才能變成迭代器。
lst = [1, 2, 3] it = iter(lst) print(next(it)) # 輸出 1 print(next(it)) # 輸出 2
一旦沒有更多元素了,就會拋出 StopIteration 異常。
立即學習“Python免費學習筆記(深入)”;
什么是生成器(Generator)?
生成器是一種簡化版的迭代器,它不需要自己實現 __next__(),而是通過函數中的 yield 來自動處理。你每次調用 next() 或者在 for 循環中使用時,函數會從上次暫停的地方繼續執行。
舉個簡單的例子:
def my_generator(): yield 1 yield 2 yield 3 g = my_generator() print(next(g)) # 輸出 1 print(next(g)) # 輸出 2
每調用一次 next(),函數就執行到下一個 yield 然后暫停,保存當前狀態。這樣做的好處是:不用一次性把所有數據加載進內存,適合處理大數據或無限序列。
yield 的作用到底是什么?
很多人以為 yield 就是返回值,其實它更像是“暫停并返回”。關鍵點有三個:
- 保存函數狀態:函數執行到 yield 時暫停,下次繼續執行是從 yield 后面開始。
- 惰性求值(Lazy Evaluation):只有真正需要的時候才計算下一個值。
- 節省內存:尤其適合處理大文件、大數據流等場景。
舉個實際的例子:讀取一個大文件,一行一行處理:
def read_large_file(file_path): with open(file_path, 'r') as f: for line in f: yield line.strip()
這個函數不會一次性把整個文件讀進內存,而是每次只讀一行,效率高得多。
yield 和 return 有什么區別?
- return 是直接返回結果,并結束函數;
- yield 是返回一個值,但函數狀態被保留,下次還能繼續執行。
還有一個細節是,使用 yield 的函數返回的是一個生成器對象,而不是直接執行函數體。
例如:
def func(): return 1 def gen_func(): yield 1 print(func()) # 輸出 1 print(gen_func()) # 輸出 <generator object ...>
使用 yield 的一些技巧
-
可以配合循環動態生成值,比如斐波那契數列:
def fib(): a, b = 0, 1 while True: yield a a, b = b, a + b
-
yield from 可以用來嵌套生成器,簡化代碼結構:
def sub_gen(): yield 1 yield 2 def main_gen(): yield from sub_gen() yield 3 for i in main_gen(): print(i)
-
多個 yield 之間可以穿插邏輯處理,比如網絡請求、狀態檢查等。
總的來說,yield 是讓函數具備“邊執行邊產出”的能力,非常適合那些需要按需生成數據的場景。雖然寫法看起來簡單,但背后機制很巧妙。理解清楚之后,你會發現它在很多實際項目中都非常有用。
基本上就這些。