迭代器
- 一、内置类型转换为迭代器
-
- [1. 列表 (List) → 迭代器](#1. 列表 (List) → 迭代器)
- [2. 元组 (Tuple) → 迭代器](#2. 元组 (Tuple) → 迭代器)
- [3. 字典 (Dict) → 迭代器](#3. 字典 (Dict) → 迭代器)
- [4. 字符串 (String) → 迭代器](#4. 字符串 (String) → 迭代器)
- [5. 集合 (Set) → 迭代器](#5. 集合 (Set) → 迭代器)
- 转换为迭代器的不同方法对比
- 完整示例:各种数据类型的迭代
- 实际应用:数据处理
- 重要注意事项
- 二、直接定义迭代器的3种方法
-
- [方法1:使用 生成器函数(最常用)](#方法1:使用 生成器函数(最常用))
- [方法2:使用 生成器表达式(简洁版)](#方法2:使用 生成器表达式(简洁版))
-
- [方法3:创建 迭代器类(最灵活)](#方法3:创建 迭代器类(最灵活))
- 三、迭代器的内存优势
-
-
- [对比:列表 vs 生成器](#对比:列表 vs 生成器)
-
- 四、高级迭代器技巧
-
- [1. `itertools` 模块(标准库中的迭代器工具)](#1.
itertools模块(标准库中的迭代器工具)) - [2. `yield from` 语法](#2.
yield from语法)
- [1. `itertools` 模块(标准库中的迭代器工具)](#1.
- 五、如何选择合适的迭代器定义方式
- 六、总结
Python 中不仅可以转换基本类型为迭代器,还可以直接定义自定义的迭代器。 这是 Python 非常强大的特性。
一、内置类型转换为迭代器
1. 列表 (List) → 迭代器
python
my_list = [1, 2, 3, 4, 5]
list_iter = iter(my_list)
print(next(list_iter)) # 输出: 1
print(next(list_iter)) # 输出: 2
print(next(list_iter)) # 输出: 3
# 也可以用 for 循环
for item in list_iter: # 从第4个元素开始
print(item) # 输出: 4, 5
2. 元组 (Tuple) → 迭代器
python
my_tuple = ('apple', 'banana', 'cherry')
tuple_iter = iter(my_tuple)
print(next(tuple_iter)) # 'apple'
print(next(tuple_iter)) # 'banana'
# 转换为列表查看剩余
print(list(tuple_iter)) # ['cherry']
3. 字典 (Dict) → 迭代器
字典有多种迭代方式:
python
my_dict = {'name': 'Alice', 'age': 25, 'city': 'Beijing'}
# 方法1:默认迭代键(keys)
dict_iter_keys = iter(my_dict)
print(next(dict_iter_keys)) # 'name'(Python 3.7+ 保持插入顺序)
print(next(dict_iter_keys)) # 'age'
# 方法2:明确迭代键
dict_iter = iter(my_dict.keys())
print(next(dict_iter)) # 'name'
# 方法3:迭代值
dict_iter_values = iter(my_dict.values())
print(next(dict_iter_values)) # 'Alice'
# 方法4:迭代键值对
dict_iter_items = iter(my_dict.items())
print(next(dict_iter_items)) # ('name', 'Alice')
4. 字符串 (String) → 迭代器
字符串也可以迭代:
python
my_string = "Hello"
str_iter = iter(my_string)
print(next(str_iter)) # 'H'
print(next(str_iter)) # 'e'
print(''.join(str_iter)) # 'llo'
5. 集合 (Set) → 迭代器
python
my_set = {1, 3, 5, 7, 9}
set_iter = iter(my_set)
print(next(set_iter)) # 1(集合无序,顺序不确定)
print(next(set_iter)) # 3
转换为迭代器的不同方法对比
| 数据类型 | 创建迭代器方法 | 迭代内容 | 示例 |
|---|---|---|---|
| 列表 | iter(lst) |
列表元素 | [1, 2, 3] → 1, 2, 3 |
| 元组 | iter(tup) |
元组元素 | ('a', 'b') → 'a', 'b' |
| 字典 | iter(dict) |
字典的键 | {'a':1} → 'a' |
| 字典键 | iter(dict.keys()) |
字典的键 | {'a':1} → 'a' |
| 字典值 | iter(dict.values()) |
字典的值 | {'a':1} → 1 |
| 字典项 | iter(dict.items()) |
(键, 值)对 | {'a':1} → ('a', 1) |
| 字符串 | iter(string) |
单个字符 | "hi" → 'h', 'i' |
| 集合 | iter(set) |
集合元素 | {1, 2} → 1, 2(顺序不定) |
完整示例:各种数据类型的迭代
python
# 定义各种数据结构
my_list = [10, 20, 30]
my_tuple = ('x', 'y', 'z')
my_dict = {'a': 1, 'b': 2, 'c': 3}
my_string = "Python"
my_set = {100, 200, 300}
def iterate_data(data, data_type):
"""通用迭代函数"""
print(f"\n迭代 {data_type}:")
iterator = iter(data)
try:
for i in range(5): # 最多尝试5次
print(f" 第{i+1}次next(): {next(iterator)}")
except StopIteration:
print(" 迭代结束")
# 测试各种类型
iterate_data(my_list, "列表")
iterate_data(my_tuple, "元组")
iterate_data(my_dict, "字典(默认迭代键)")
iterate_data(my_dict.values(), "字典的值")
iterate_data(my_string, "字符串")
iterate_data(my_set, "集合")
实际应用:数据处理
场景1:批量处理数据
python
# 有一个数据列表,需要分批处理
data_list = list(range(100)) # 0-99
data_iter = iter(data_list)
batch_size = 10
batch_num = 0
while True:
batch = []
try:
for _ in range(batch_size):
batch.append(next(data_iter))
except StopIteration:
if batch: # 处理最后一批
print(f"批次 {batch_num}: {batch}")
break
print(f"批次 {batch_num}: {batch}")
batch_num += 1
场景2:链式迭代多个数据集
python
# 合并多个数据源的迭代器
def chain_iterators(*iterables):
"""链式迭代多个可迭代对象"""
for iterable in iterables:
yield from iterable
# 使用
list_data = [1, 2, 3]
tuple_data = (4, 5, 6)
dict_keys = {'a': 1, 'b': 2}.keys()
combined_iter = chain_iterators(list_data, tuple_data, dict_keys)
print(list(combined_iter)) # [1, 2, 3, 4, 5, 6, 'a', 'b']
场景3:创建自定义迭代器
python
class DataLoader:
"""模拟PyTorch DataLoader的简单版本"""
def __init__(self, data, batch_size=2):
self.data = data
self.batch_size = batch_size
def __iter__(self):
self.index = 0
return self
def __next__(self):
if self.index >= len(self.data):
raise StopIteration
batch = self.data[self.index:self.index + self.batch_size]
self.index += self.batch_size
return batch
# 使用自定义迭代器
loader = DataLoader([1, 2, 3, 4, 5, 6], batch_size=2)
for batch in loader:
print(f"批次: {batch}")
# 输出:
# 批次: [1, 2]
# 批次: [3, 4]
# 批次: [5, 6]
重要注意事项
-
迭代器只能前进不能后退:
pythondata = [1, 2, 3, 4] it = iter(data) print(next(it)) # 1 print(next(it)) # 2 # 无法回到1 -
迭代器会消耗数据:
pythonit = iter([1, 2, 3]) list(it) # [1, 2, 3] list(it) # [],已经耗尽 -
可迭代对象 vs 迭代器:
pythonlst = [1, 2, 3] # 可迭代对象 it = iter(lst) # 迭代器 # 可迭代对象可以多次创建迭代器 it1 = iter(lst) it2 = iter(lst) -
判断是否为迭代器:
pythonfrom collections.abc import Iterator lst = [1, 2, 3] it = iter(lst) print(isinstance(lst, Iterator)) # False print(isinstance(it, Iterator)) # True
二、直接定义迭代器的3种方法
方法1:使用 生成器函数(最常用)
python
def my_generator(start, end):
"""生成从 start 到 end 的整数"""
current = start
while current <= end:
yield current # yield 是关键!
current += 1
# 使用
gen = my_generator(1, 5) # 这已经是一个迭代器
print(type(gen)) # <class 'generator'>
print(next(gen)) # 1
print(next(gen)) # 2
print(list(gen)) # [3, 4, 5](剩余的部分)
方法2:使用 生成器表达式(简洁版)
python
# 类似列表推导式,但用圆括号
gen_expr = (x**2 for x in range(5)) # 生成器表达式
print(type(gen_expr)) # <class 'generator'>
print(next(gen_expr)) # 0
print(next(gen_expr)) # 1
print(list(gen_expr)) # [4, 9, 16]
方法3:创建 迭代器类(最灵活)
python
class MyIterator:
"""自定义迭代器类"""
def __init__(self, start, end):
self.current = start
self.end = end
def __iter__(self):
"""返回迭代器自身"""
return self
def __next__(self):
"""返回下一个值"""
if self.current > self.end:
raise StopIteration
else:
value = self.current
self.current += 1
return value
# 使用
my_iter = MyIterator(1, 3)
print(type(my_iter)) # <class '__main__.MyIterator'>
print(next(my_iter)) # 1
print(next(my_iter)) # 2
print(next(my_iter)) # 3
print(next(my_iter)) # 抛出 StopIteration
三、迭代器的内存优势
对比:列表 vs 生成器
python
import sys
# 方法1:使用列表(占用大量内存)
def get_numbers_list(n):
"""返回包含前n个数字的列表"""
numbers = []
for i in range(n):
numbers.append(i)
return numbers
# 方法2:使用生成器(节省内存)
def get_numbers_generator(n):
"""生成前n个数字"""
for i in range(n):
yield i
# 对比内存使用
n = 1000000
# 列表:一次性在内存中创建所有元素
list_numbers = get_numbers_list(n)
print(f"列表占用内存: {sys.getsizeof(list_numbers)} 字节") # 约 8MB
# 生成器:一次只生成一个元素
gen_numbers = get_numbers_generator(n)
print(f"生成器占用内存: {sys.getsizeof(gen_numbers)} 字节") # 约 100 字节
# 但只能使用一次
print(sum(gen_numbers)) # 正常工作
print(sum(gen_numbers)) # 0(生成器已耗尽)
四、高级迭代器技巧
1. itertools 模块(标准库中的迭代器工具)
python
import itertools
# 无限迭代器
counter = itertools.count(start=10, step=2)
print(next(counter)) # 10
print(next(counter)) # 12
print(next(counter)) # 14
# 循环迭代器
cycle_iter = itertools.cycle(['A', 'B', 'C'])
print(next(cycle_iter)) # A
print(next(cycle_iter)) # B
print(next(cycle_iter)) # C
print(next(cycle_iter)) # A(又回到开头)
# 排列组合
permutations = itertools.permutations([1, 2, 3], 2)
print(list(permutations)) # [(1,2), (1,3), (2,1), (2,3), (3,1), (3,2)]
2. yield from 语法
python
def chain_generators(*iterables):
"""连接多个生成器"""
for it in iterables:
yield from it # 委托给子生成器
# 使用
result = chain_generators([1, 2, 3], (4, 5, 6), {7, 8, 9})
print(list(result)) # [1, 2, 3, 4, 5, 6, 8, 9, 7](集合顺序不确定)
五、如何选择合适的迭代器定义方式
| 场景 | 推荐方式 | 示例 |
|---|---|---|
| 简单序列生成 | 生成器表达式 | (x**2 for x in range(10)) |
| 复杂数据生成 | 生成器函数 | def read_file(): yield line |
| 需要状态维护 | 迭代器类 | class DataLoader: |
| 需要重复杂用 | 可迭代对象 | 实现 __iter__() 返回新迭代器 |
| 组合现有迭代器 | itertools 模块 |
itertools.chain() |
六、总结
-
Python 可以直接定义迭代器,而不仅限于转换基本类型
-
三种主要方法:
- 生成器函数(
yield关键字) - 生成器表达式(圆括号推导式)
- 迭代器类(实现
__iter__和__next__)
- 生成器函数(
-
在深度学习中,自定义迭代器非常有用,可以:
- 实现自定义 DataLoader
- 处理流式数据
- 节省内存(特别是处理大数据时)
- 实现复杂的数据预处理流
-
所有可迭代对象 都可以用
iter()转换为迭代器 -
列表、元组:迭代元素
-
字典 :默认迭代键,也可用
.values()、.items()迭代值和键值对 -
字符串:迭代字符
-
集合:迭代元素(顺序不确定)
-
迭代器是单向的、消耗性的 ,使用
next()逐个获取元素