爲什麼需要迭代器和生成器?¶
在Python中處理數據時,我們經常會遇到這樣的問題:如果數據量很大(比如幾GB的文件、海量的日誌記錄),或者數據是“無限”的(比如不斷接收的傳感器數據),直接把所有數據加載到內存中會導致程序崩潰,或者運行得非常緩慢。這時候,迭代器和生成器就能派上用場了——它們可以“按需”生成數據,而不是一次性加載所有內容到內存,從而節省內存並提高效率。
一、迭代器:逐個“吐出”數據的對象¶
什麼是迭代器?
迭代器是一個“數據訪問接口”,它能讓你逐個獲取數據集合中的元素,而且只能向前迭代(不能後退)。它必須實現兩個核心方法:
- __iter__():返回迭代器對象本身(讓for循環能識別它是可迭代的)。
- __next__():返回下一個元素,如果沒有更多元素,會拋出StopIteration異常。
如何創建和使用迭代器?
Python中,幾乎所有可迭代對象(如列表、元組、字符串、字典等)都可以通過iter()函數轉換爲迭代器。例如:
# 定義一個列表
my_list = [1, 2, 3, 4]
# 將列表轉換爲迭代器
my_iter = iter(my_list)
# 逐個獲取元素
print(next(my_iter)) # 輸出:1
print(next(my_iter)) # 輸出:2
print(next(my_iter)) # 輸出:3
print(next(my_iter)) # 輸出:4
print(next(my_iter)) # 報錯:StopIteration(所有元素已迭代完畢)
關鍵點:
- 迭代器只能“往前走”,無法重複迭代。比如第一次迭代完後,迭代器已經“走到頭”,再次用next()會直接報錯。
- 常見的可迭代對象(列表、元組等)本身不是迭代器,但可以通過iter()轉換爲迭代器。
二、生成器:更簡單的迭代器,用yield實現¶
生成器是一種特殊的迭代器,它的語法比手動實現迭代器更簡潔,而且內存效率更高。生成器通過兩種方式創建:生成器函數(用yield關鍵字)或生成器表達式(類似列表推導式,但用圓括號)。
1. 生成器函數:用yield“暫停”和“恢復”¶
生成器函數和普通函數類似,但使用yield關鍵字替代return。當函數執行到yield時,會暫停執行並返回一個值;下次調用函數時,會從yield的下一行繼續執行。
示例1:生成器函數生成斐波那契數列
斐波那契數列是無限的(0, 1, 1, 2, 3, 5…),如果用列表生成會佔用無限內存,而生成器可以“按需”生成:
def fibonacci(n):
a, b = 0, 1
for _ in range(n):
yield a # 每次返回一個斐波那契數,暫停函數
a, b = b, a + b
# 使用生成器
fib = fibonacci(5) # 生成前5個斐波那契數
for num in fib:
print(num) # 輸出:0, 1, 1, 2, 3
示例2:生成器函數處理大文件
如果要讀取一個10GB的日誌文件,用列表一次性讀取會崩潰,而生成器可以逐行讀取:
def read_large_file(file_path):
with open(file_path, 'r') as f:
for line in f: # 文件對象本身是可迭代的,逐行讀取
yield line.strip() # 每次返回一行內容
# 使用生成器讀取文件
for line in read_large_file('big_log.txt'):
process(line) # 處理每一行數據(無需加載整個文件到內存)
2. 生成器表達式:一行實現簡單生成器¶
生成器表達式語法與列表推導式類似,但用圓括號()包裹,且不會一次性生成所有元素,而是逐個生成。
示例1:生成1-10的平方數(生成器表達式)
squares = (x**2 for x in range(10)) # 生成器表達式
print(squares) # 輸出:<generator object <genexpr> at 0x...>
for num in squares:
print(num) # 逐個輸出:0, 1, 4, 9, 16, 25, 36, 49, 64, 81
對比列表推導式:
列表推導式[x**2 for x in range(10)]會一次性生成包含所有10個平方數的列表,佔用內存;而生成器表達式(x**2 for x in range(10))只會在每次迭代時生成一個數,內存效率更高。
三、迭代器 vs 生成器:核心區別¶
| 特性 | 迭代器 | 生成器 |
|---|---|---|
| 定義方式 | 手動實現__iter__和__next__方法 |
生成器函數(yield)或生成器表達式 |
| 內存效率 | 較高,但需手動實現 | 極高,無需一次性存儲所有元素 |
| 適用場景 | 複雜迭代邏輯(如自定義序列) | 簡單的“逐個生成”場景(如大數據流) |
四、實際應用場景¶
- 處理大數據流:如讀取大文件、處理數據庫查詢結果(避免一次性加載)。
- 無限序列:如斐波那契數列、隨機數生成(無法用列表存儲無限數據)。
- 節省內存:例如生成100萬個數的平方,用生成器表達式比列表推導式節省大量內存。
五、總結¶
迭代器和生成器是Python中處理數據的“輕量級”工具,核心優勢是內存高效和按需生成。掌握它們能讓你寫出更簡潔、更高效的代碼,尤其在處理大數據或無限序列時。生成器作爲特殊的迭代器,語法更簡單(yield或生成器表達式),是初學者快速上手的優選。
從“逐個訪問元素”到“按需生成數據”,迭代器和生成器讓Python處理數據的能力更上一層樓,是每個Python開發者必備的基礎技巧。