從列表到生成器詳解Python可迭代對象的完全指南
可迭代對象是 Python 中非常重要的概念,列表、元組、字符串、字典、集合等都是可迭代對象。本文詳細介紹了可迭代對象和迭代器的區(qū)別,以及如何創(chuàng)建它們,包括用 iter()、實現(xiàn) __iter__ + __next__、用 yield 生成器等多種方式。掌握這些知識,你就能更好地理解 Python 的迭代機制,寫出更高效的代碼
1. 什么是可迭代對象
可迭代對象(Iterable) 就是可以用 for 循環(huán)遍歷的對象
通俗來說,就是"能一個一個取出元素的對象":
# 列表是可迭代對象
for item in [1, 2, 3]:
print(item) # 依次輸出 1, 2, 3
# 字符串是可迭代對象
for char in "hello":
print(char) # 依次輸出 h, e, l, l, o
# 字典是可迭代對象
for key in {"name": "Tom", "age": 18}:
print(key) # 依次輸出 name, age
技術(shù)定義
從代碼層面來說,實現(xiàn)了 __iter__ 方法的對象就是可迭代對象:
# 查看列表的__iter__方法 print([].__iter__) # <method-wrapper '__iter__' of list object at 0x...>
這個方法的作用是返回一個迭代器(Iterator),然后我們就可以用迭代器逐個獲取元素啦~
2. 常見可迭代對象類型
Python 中的可迭代對象非常豐富,主要分為以下幾類
2.1 內(nèi)置序列類型
| 類型 | 示例 | 說明 |
|---|---|---|
| 列表 | [1, 2, 3] | 有序、可變 |
| 元組 | (1, 2, 3) | 有序、不可變 |
| 字符串 | "hello" | 有序、字符序列 |
| range | range(5) | 整數(shù)序列 |
# 列表
for i in [1, 2, 3]:
print(i)
# 元組
for i in (1, 2, 3):
print(i)
# 字符串
for c in "abc":
print(c)
# range
for i in range(3):
print(i) # 0, 1, 2
2.2 集合類型
| 類型 | 示例 | 說明 |
|---|---|---|
| 集合 | {1, 2, 3} | 無序、唯一 |
| 字典 | {"a": 1} | 鍵值對 |
# 集合(遍歷的是鍵)
for i in {1, 2, 3}:
print(i)
# 字典(默認遍歷鍵)
for key in {"name": "Tom", "age": 18}:
print(key) # name, age
2.3 特殊類型
| 類型 | 示例 | 說明 |
|---|---|---|
| 文件對象 | open("file.txt") | 逐行讀取 |
| 生成器 | (i for i in range(5)) | 惰性生成,按需取值 |
| 迭代器 | iter([1,2,3]) | 消耗性遍歷,用完就沒 |
什么是消耗性遍歷?
知道了解就好,不用深究
迭代器無法二次使用,用完就沒了
it = iter([1, 2, 3])
for i in it:
print(i) # 1, 2, 3
# 二次使用:什么都不輸出,也不會報錯
for i in it:
print(i) # 不輸出
什么是惰性生成?
知道了解就好,不用深究
簡單說,生成器記錄了數(shù)據(jù)怎么生成的規(guī)則,只有當(dāng)你用 next() 或遍歷時,才會根據(jù)這個規(guī)則生成具體的值
- 列表
[1,2,3]→ 直接存了3個值 - 生成器
(x for x in range(3))→ 只存了"怎么生成"的規(guī)則,用到時才算
# 列表 → 直接存值 lst = [1, 2, 3] # 生成器 → 記錄生成規(guī)則,用next()才取值 gen = (x * 2 for x in range(3)) print(next(gen)) # 0 print(next(gen)) # 2 print(next(gen)) # 4
# 生成器表達式
gen = (i * 2 for i in range(3))
for i in gen:
print(i) # 0, 2, 4
# range 對象
for i in range(5):
print(i)
Tip:幾乎所有可以"逐個訪問"的數(shù)據(jù)結(jié)構(gòu)都是可迭代對象!
3. 如何判斷可迭代對象
可以用 isinstance() 配合 collections.abc.Iterable 來判斷
from collections.abc import Iterable
# 測試常見對象
print(isinstance([1, 2, 3], Iterable)) # True - 列表
print(isinstance("hello", Iterable)) # True - 字符串
print(isinstance((1, 2, 3), Iterable)) # True - 元組
print(isinstance({1, 2, 3}, Iterable)) # True - 集合
print(isinstance({"a": 1}, Iterable)) # True - 字典
print(isinstance(range(5), Iterable)) # True - range
print(isinstance((x for x in range(3)), Iterable)) # True - 生成器
# 非可迭代對象
print(isinstance(100, Iterable)) # False - 數(shù)字
print(isinstance(None, Iterable)) # False - None
原理
判斷依據(jù):對象是否實現(xiàn)了 __iter__ 方法
# 列表有 __iter__ 方法 print(hasattr([1, 2, 3], '__iter__')) # True # 數(shù)字沒有 print(hasattr(100, '__iter__')) # False
推薦用 isinstance(obj, Iterable) 的方式,更規(guī)范可靠!
4. 迭代器與可迭代對象的區(qū)別
這兩個概念很容易混淆,來一張圖說明:
graph LR
A[可迭代對象<br/>Iterable] -->|實現(xiàn)__iter__| B[返回迭代器]
B --> C[迭代器<br/>Iterator]
C -->|實現(xiàn)__next__| D[逐個取值]
style A fill:#e3f2fd,stroke:#1976d2
style C fill:#ffebee,stroke:#d32f2f
核心區(qū)別
| 可迭代對象 (Iterable) | 迭代器 (Iterator) | |
|---|---|---|
| 實現(xiàn)方法 | __iter__ | __iter__ + __next__ |
| 能否獲取下一個值 | ? 不能 | ? 能 |
| 能否二次遍歷 | ? 可以 | ? 只能一次 |
| 例子 | 列表、字符串、字典 | 生成器、iter([1,2,3]) |
# 列表 → 可迭代對象 lst = [1, 2, 3] print(hasattr(lst, '__iter__')) # True print(hasattr(lst, '__next__')) # False # iter() 返回的是迭代器 it = iter(lst) print(hasattr(it, '__iter__')) # True print(hasattr(it, '__next__')) # True # 用 next() 獲取值 print(next(it)) # 1 print(next(it)) # 2 print(next(it)) # 3 # print(next(it)) # StopIteration 異常
關(guān)系總結(jié)
可迭代對象 實現(xiàn)了 __iter__,可以返回 迭代器
迭代器 實現(xiàn)了 __next__,可以逐個取值
簡單說:迭代器 = 可迭代對象 + 取值能力
5. 如何創(chuàng)建可迭代對象和迭代器
5.1 創(chuàng)建可迭代對象
iter() 是 Python 內(nèi)置函數(shù),用于獲取可迭代對象的迭代器:
# iter(可迭代對象) → 返回迭代器 lst = [1, 2, 3] it = iter(lst) # 獲取迭代器 print(next(it)) # 1 # 也可以直接用 iter(obj) # 相當(dāng)于調(diào)用 obj.__iter__()
只需要實現(xiàn) __iter__ 方法,返回一個迭代器即可:
# 方式一:用 iter() 返回迭代器
class MyIterable:
def __init__(self, data):
self.data = data
def __iter__(self):
# 返回迭代器對象
return iter(self.data)
# 方式二:同時實現(xiàn) __iter__ + __next__,返回 self
class MyIterable2:
def __init__(self, data):
self.data = data
self.index = 0
def __iter__(self):
return self # 返回自身
def __next__(self):
if self.index >= len(self.data):
raise StopIteration
value = self.data[self.index]
self.index += 1
return value
# 使用
obj = MyIterable([1, 2, 3])
for i in obj:
print(i) # 1, 2, 3
方式三:舊式兼容(了解即可)
Python 早期版本沒有 __iter__,可以用 __getitem__ 實現(xiàn)可迭代:
class MyIterable3:
def __init__(self, data):
self.data = data
def __getitem__(self, index):
return self.data[index]
# Python 會自動從 index 0 開始嘗試調(diào)用 __getitem__
obj = MyIterable3([1, 2, 3])
for i in obj:
print(i) # 1, 2, 3
這種方式是為了兼容性,了解就行,現(xiàn)在推薦用方式一或方式二!
5.2 創(chuàng)建迭代器
需要同時實現(xiàn) __iter__ 和 __next__ 方法:
class MyIterator:
def __init__(self, data):
self.data = data
self.index = 0
def __iter__(self):
return self # 返回自身
def __next__(self):
if self.index >= len(self.data):
raise StopIteration # 迭代結(jié)束
value = self.data[self.index]
self.index += 1
return value
# 使用
it = MyIterator([1, 2, 3])
print(next(it)) # 1
print(next(it)) # 2
print(next(it)) # 3
# next(it) # StopIteration
5.3 用 yield 創(chuàng)建生成器(推薦!)
用 yield 關(guān)鍵字,不需要 iter(),不需要寫類,直接創(chuàng)建可迭代對象:
# 用 yield 的函數(shù) → 生成器
def my_generator():
yield 1
yield 2
yield 3
# 調(diào)用函數(shù)不會執(zhí)行,只是返回生成器對象
gen = my_generator()
print(gen) # <generator object my_generator at ...>
# 生成器本身就是迭代器,不需要 iter()
for i in gen:
print(i) # 1, 2, 3
特點:
- 調(diào)用函數(shù)不執(zhí)行,只是返回生成器對象
- 用
next()或遍歷時才執(zhí)行 - 用到才生成值,不占內(nèi)存
最推薦的方式,代碼最簡潔!
6. 總結(jié)
這篇文章我們學(xué)習(xí)了 Python 可迭代對象的知識,來回顧一下:
核心概念
| 概念 | 說明 |
|---|---|
| 可迭代對象 | 實現(xiàn)了 __iter__,可以用 for 遍歷 |
| 迭代器 | 實現(xiàn)了 __iter__ + __next__,可以逐個取值 |
| 生成器 | 用 yield 創(chuàng)建,惰性生成,用到才取值 |
創(chuàng)建方式
| 方式 | 代碼 | 特點 |
|---|---|---|
| 方式一 | __iter__ + iter() | 返回已有的迭代器 |
| 方式二 | __iter__ + __next__ + 返回 self | 自身即是迭代器 |
| 方式三 | __getitem__ | 舊式兼容,了解即可 |
| 方式四 | yield 生成器函數(shù) | 最推薦,簡潔高效 |
實際應(yīng)用
- 數(shù)據(jù)處理:大文件、數(shù)據(jù)庫查詢結(jié)果(用生成器省內(nèi)存)
- 無限序列:數(shù)學(xué)序列、實時數(shù)據(jù)流
- 自定義遍歷:按特定規(guī)則遍歷對象
到此這篇關(guān)于從列表到生成器詳解Python可迭代對象的完全指南的文章就介紹到這了,更多相關(guān)Python可迭代對象內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
零基礎(chǔ)實現(xiàn)Python到Java代碼轉(zhuǎn)換的實戰(zhàn)全攻略
這篇文章主要為大家詳細介紹了零基礎(chǔ)實現(xiàn)Python到Java代碼轉(zhuǎn)換的相關(guān)方法,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2025-12-12

