迭代器
- 一、内置类型转换为迭代器
- 1. 列表 (List) → 迭代器
- 2. 元组 (Tuple) → 迭代器
- 3. 字典 (Dict) → 迭代器
- 4. 字符串 (String) → 迭代器
- 5. 集合 (Set) → 迭代器
- 转换为迭代器的不同方法对比
- 完整示例:各种数据类型的迭代
- 实际应用:数据处理
- 场景1:批量处理数据
- 场景2:链式迭代多个数据集
- 场景3:创建自定义迭代器
- 重要注意事项
- 二、直接定义迭代器的3种方法
- 方法1:使用 生成器函数(最常用)
- 方法2:使用 生成器表达式(简洁版)
- 方法3:创建 迭代器类(最灵活)
- 三、迭代器的内存优势
- 对比:列表 vs 生成器
- 四、高级迭代器技巧
- 1. `itertools` 模块(标准库中的迭代器工具)
- 2. `yield from` 语法
- 五、如何选择合适的迭代器定义方式
- 六、总结
Python 中不仅可以转换基本类型为迭代器,还可以直接定义自定义的迭代器。 这是 Python 非常强大的特性。
一、内置类型转换为迭代器
1. 列表 (List) → 迭代器
my_list=[1,2,3,4,5]list_iter=iter(my_list)print(next(list_iter))# 输出: 1print(next(list_iter))# 输出: 2print(next(list_iter))# 输出: 3# 也可以用 for 循环foriteminlist_iter:# 从第4个元素开始print(item)# 输出: 4, 52. 元组 (Tuple) → 迭代器
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) → 迭代器
字典有多种迭代方式:
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) → 迭代器
字符串也可以迭代:
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) → 迭代器
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(顺序不定) |
完整示例:各种数据类型的迭代
# 定义各种数据结构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}defiterate_data(data,data_type):"""通用迭代函数"""print(f"\n迭代{data_type}:")iterator=iter(data)try:foriinrange(5):# 最多尝试5次print(f" 第{i+1}次next():{next(iterator)}")exceptStopIteration: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:批量处理数据
# 有一个数据列表,需要分批处理data_list=list(range(100))# 0-99data_iter=iter(data_list)batch_size=10batch_num=0whileTrue:batch=[]try:for_inrange(batch_size):batch.append(next(data_iter))exceptStopIteration:ifbatch:# 处理最后一批print(f"批次{batch_num}:{batch}")breakprint(f"批次{batch_num}:{batch}")batch_num+=1场景2:链式迭代多个数据集
# 合并多个数据源的迭代器defchain_iterators(*iterables):"""链式迭代多个可迭代对象"""foriterableiniterables:yieldfromiterable# 使用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:创建自定义迭代器
classDataLoader:"""模拟PyTorch DataLoader的简单版本"""def__init__(self,data,batch_size=2):self.data=data self.batch_size=batch_sizedef__iter__(self):self.index=0returnselfdef__next__(self):ifself.index>=len(self.data):raiseStopIteration batch=self.data[self.index:self.index+self.batch_size]self.index+=self.batch_sizereturnbatch# 使用自定义迭代器loader=DataLoader([1,2,3,4,5,6],batch_size=2)forbatchinloader:print(f"批次:{batch}")# 输出:# 批次: [1, 2]# 批次: [3, 4]# 批次: [5, 6]重要注意事项
迭代器只能前进不能后退:
data=[1,2,3,4]it=iter(data)print(next(it))# 1print(next(it))# 2# 无法回到1迭代器会消耗数据:
it=iter([1,2,3])list(it)# [1, 2, 3]list(it)# [],已经耗尽可迭代对象 vs 迭代器:
lst=[1,2,3]# 可迭代对象it=iter(lst)# 迭代器# 可迭代对象可以多次创建迭代器it1=iter(lst)it2=iter(lst)判断是否为迭代器:
fromcollections.abcimportIterator lst=[1,2,3]it=iter(lst)print(isinstance(lst,Iterator))# Falseprint(isinstance(it,Iterator))# True
二、直接定义迭代器的3种方法
方法1:使用 生成器函数(最常用)
defmy_generator(start,end):"""生成从 start 到 end 的整数"""current=startwhilecurrent<=end:yieldcurrent# yield 是关键!current+=1# 使用gen=my_generator(1,5)# 这已经是一个迭代器print(type(gen))# <class 'generator'>print(next(gen))# 1print(next(gen))# 2print(list(gen))# [3, 4, 5](剩余的部分)方法2:使用 生成器表达式(简洁版)
# 类似列表推导式,但用圆括号gen_expr=(x**2forxinrange(5))# 生成器表达式print(type(gen_expr))# <class 'generator'>print(next(gen_expr))# 0print(next(gen_expr))# 1print(list(gen_expr))# [4, 9, 16]方法3:创建 迭代器类(最灵活)
classMyIterator:"""自定义迭代器类"""def__init__(self,start,end):self.current=start self.end=enddef__iter__(self):"""返回迭代器自身"""returnselfdef__next__(self):"""返回下一个值"""ifself.current>self.end:raiseStopIterationelse:value=self.current self.current+=1returnvalue# 使用my_iter=MyIterator(1,3)print(type(my_iter))# <class '__main__.MyIterator'>print(next(my_iter))# 1print(next(my_iter))# 2print(next(my_iter))# 3print(next(my_iter))# 抛出 StopIteration三、迭代器的内存优势
对比:列表 vs 生成器
importsys# 方法1:使用列表(占用大量内存)defget_numbers_list(n):"""返回包含前n个数字的列表"""numbers=[]foriinrange(n):numbers.append(i)returnnumbers# 方法2:使用生成器(节省内存)defget_numbers_generator(n):"""生成前n个数字"""foriinrange(n):yieldi# 对比内存使用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模块(标准库中的迭代器工具)
importitertools# 无限迭代器counter=itertools.count(start=10,step=2)print(next(counter))# 10print(next(counter))# 12print(next(counter))# 14# 循环迭代器cycle_iter=itertools.cycle(['A','B','C'])print(next(cycle_iter))# Aprint(next(cycle_iter))# Bprint(next(cycle_iter))# Cprint(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语法
defchain_generators(*iterables):"""连接多个生成器"""foritiniterables:yieldfromit# 委托给子生成器# 使用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()逐个获取元素