《零基础入门AI: Python 迭代器和生成器的区别及其实现方式和使用场景总结》
迭代器和生成器都是Python中实现“惰性计算”的核心工具,它们通过按需生成数据来减少内存占用,这在AI领域处理大规模数据集(如图像、文本)时尤为重要。迭代器是更底层的实现,需要手动维护状态和迭代协议,适合构建复杂的自定义可迭代对象。生成器是迭代器的“语法糖”,通过yield自动实现迭代协议,代码更简洁,是处理大数据和简化迭代逻辑的首选。记住一个简单的判断:如果能用几行代码实现迭代逻辑,优先用生成
一、迭代器的基本概念、实现方式及使用场景
(一)基本概念
迭代器(Iterator)是一种可以被遍历的对象,它能够逐个返回序列中的元素。从专业角度来说,迭代器是实现了迭代协议(Iterator Protocol)的对象,这个协议要求对象必须包含__iter__()
方法和__next__()
方法。简单理解,迭代器就像一个数据的 “传送带”,我们每次从上面取下一个数据,直到取完为止。
需要注意的是,迭代器具有一次性特性 —— 一旦遍历结束(即__next__()
抛出StopIteration
),该迭代器对象就无法再次使用,若需重新遍历,必须重新创建迭代器实例。
(二)实现方式
要自定义一个迭代器,需要在类中实现__iter__()
和__next__()
方法:
-
__iter__()
方法:返回迭代器对象本身,这使得迭代器可以用于for循环等迭代场景( for 循环会自动调用__iter__()
获取迭代器)。 -
__next__()
方法:返回序列中的下一个元素,当没有元素可返回时,会抛出StopIteration
异常,以此终止迭代。
示例:
class NumberIterator:
def __init__(self, start, end):
self.current = start # 维护当前迭代位置
self.end = end
def __iter__(self):
return self # 迭代器自身就是可迭代对象
def __next__(self):
if self.current < self.end:
result = self.current
self.current += 1 # 手动更新迭代状态
return result
else:
raise StopIteration # 终止迭代的信号
# 使用迭代器
num_iter = NumberIterator(1, 5)
print(list(num_iter)) # 输出:[1, 2, 3, 4]
print(list(num_iter)) # 输出:[](迭代器已耗尽)
通过二次调用list(num_iter)
展示迭代器的一次性特性。
(三)使用场景
- 处理大量数据:当数据量很大时,使用迭代器可以避免一次性将所有数据加载到内存中,而是按需生成数据,节省内存空间。例如,读取一个几 GB 的大文件时,使用迭代器逐行读取会非常高效。
示例(读取大文件):
class LargeFileReader:
def __init__(self, filename):
self.filename = filename
self.file = open(filename, 'r')
def __iter__(self):
return self
def __next__(self):
line = self.file.readline()
if line:
return line.strip()
else:
self.file.close()
raise StopIteration
# 使用迭代器读取大文件(仅占用单行数据的内存)
for line in LargeFileReader ('large_file.txt'):
process (line) # 假设 process 是数据处理函数
- 自定义可迭代对象:当我们需要创建一个自定义的序列类型,并且希望它能够被迭代时,就可以通过实现迭代器来实现。比如自定义一个日期迭代器,用于遍历一段时间内的日期。
示例(日期迭代器):
from datetime import date, timedelta
class DateRangeIterator:
def __init__(self, start_date, end_date):
self.current_date = start_date
self.end_date = end_date
def __iter__(self):
return self
def __next__(self):
if self.current_date < self.end_date:
result = self.current_date
self.current_date += timedelta(days=1)
return result
else:
raise StopIteration
# 遍历2023年1月的前5天
start = date(2023, 1, 1)
end = date(2023, 1, 6)
for d in DateRangeIterator(start, end):
print(d.strftime("%Y-%m-%d")) # 输出2023-01-01至2023-01-05
二、生成器的基本概念、实现方式及使用场景
(一)基本概念
生成器(Generator)是一种特殊的迭代器,它不需要像普通迭代器那样显式地实现__iter__()
和__next__()
方法 ——Python 会自动为生成器实现迭代协议。生成器的核心特性是状态暂停与恢复:当执行到yield
语句时,函数会暂停并返回值,下次调用时从暂停处继续执行(保留局部变量的状态)。可以把生成器看作是 “按需生产数据的工厂”,只有在被请求时才会生成下一个值。
(二)实现方式
生成器有两种实现方式:
- 生成器函数:在函数中使用
yield
关键字来返回数据,函数执行到yield
时会暂停,并将yield
后面的值返回,下次调用时从暂停的位置继续执行。
示例(生成器函数的状态保存):
def number_generator(start, end):
current = start
while current < end:
yield current # 暂停并返回值,保留current的状态
current += 1
# 生成器的状态演示
gen = number_generator (1, 5)
print (next (gen)) # 输出:1(执行到 yield 后暂停)
print (next (gen)) # 输出:2(从 yield 后继续执行)
- 生成器表达式:类似于列表推导式,但使用圆括号
()
而不是方括号[]
,它会返回一个生成器对象。
示例(生成器表达式与列表推导式的对比):
# 生成器表达式(仅定义,不计算)
gen_expr = (x * 2 for x in range(1, 5))
print(gen_expr) # 输出:<generator object <genexpr> at 0x...>
# 列表推导式(立即计算并生成所有元素)
list_comp = [x * 2 for x in range(1, 5)]
print(list_comp) # 输出:[2, 4, 6, 8]
# 生成器表达式按需计算
print(list(gen_expr)) # 输出:[2, 4, 6, 8]
突出生成器 “延迟计算” 的特性。
(三)使用场景
-
处理大数据流:和迭代器类似,生成器也适合处理大量数据或无限数据流,因为它不会一次性生成所有数据,而是按需生成,能有效节省内存。例如,生成无限的斐波那契数列。
示例(AI 训练数据生成器):
def data_generator(file_path, batch_size): """AI训练中的批量数据生成器""" while True: # 无限循环,持续生成数据 batch = [] with open(file_path, 'r') as f: for line in f: batch.append(preprocess(line)) # 假设preprocess是预处理函数 if len(batch) == batch_size: yield batch # 返回一个批次的数据 batch = [] if batch: # 处理最后一批不足batch_size的数据 yield batch # 使用生成器按批次加载数据(内存仅存一个批次) for batch in data_generator ('train_data.txt', 32): model.train (batch) # 假设 model 是 AI 模型
-
简化迭代器代码:当我们需要实现一个迭代器时,如果使用生成器来实现,代码会更加简洁易懂。相比显式实现
__iter__()
和__next__()
方法,生成器函数的代码量更少,逻辑也更清晰。示例(用生成器简化日期迭代器):
from datetime import date, timedelta def date_range_generator(start_date, end_date): current_date = start_date while current_date < end_date: yield current_date current_date += timedelta(days=1) # 代码量比迭代器实现减少50% for d in date_range_generator(date(2023,1,1), date(2023,1,6)): print(d)
-
简单的协程功能:生成器可以通过send()方法接收外部传入的数据,实现函数间的交互。这在需要分步处理数据的场景中很有用(如流水线式数据处理)。
示例(生成器接收数据):
def accumulator(): total = 0 while True: num = yield total # 先返回total,再接收num if num is None: break total += num acc = accumulator () next (acc) # 启动生成器(执行到 yield 处) print (acc.send (3)) # 发送 3,返回 3(0+3) print (acc.send (5)) # 发送 5,返回 8(3+5) acc.send (None) # 结束生成器
展示生成器的双向通信能力(入门级示例,不深入协程细节)。
三、迭代器和生成器的区别
区别方面 | 迭代器 | 生成器 |
---|---|---|
实现方式 | 需显式实现__iter__() 和__next__() |
通过yield 函数或() 表达式实现 |
状态维护 | 需手动定义变量保存状态(如current ) |
自动保存函数局部变量状态 |
代码复杂度 | 实现较繁琐(至少3个方法) | 代码简洁(一行yield 即可) |
一次性特性 | 通常是一次性的(耗尽后需重建) | 天然一次性(耗尽后需重建) |
交互能力 | 仅能返回数据 | 可通过send() 接收外部数据(初级协程) |
典型应用 | 复杂自定义序列(如数据库结果集) | 大数据流、迭代器简化实现、分步处理 |
四、总结
迭代器和生成器都是Python中实现“惰性计算”的核心工具,它们通过按需生成数据来减少内存占用,这在AI领域处理大规模数据集(如图像、文本)时尤为重要。
- 迭代器是更底层的实现,需要手动维护状态和迭代协议,适合构建复杂的自定义可迭代对象。
- 生成器是迭代器的“语法糖”,通过
yield
自动实现迭代协议,代码更简洁,是处理大数据和简化迭代逻辑的首选。
记住一个简单的判断:如果能用几行代码实现迭代逻辑,优先用生成器;如果需要复杂的状态管理或自定义行为,再考虑手动实现迭代器。掌握这两个工具,能让你的数据处理代码更高效、更易维护。

GitCode 天启AI是一款由 GitCode 团队打造的智能助手,基于先进的LLM(大语言模型)与多智能体 Agent 技术构建,致力于为用户提供高效、智能、多模态的创作与开发支持。它不仅支持自然语言对话,还具备处理文件、生成 PPT、撰写分析报告、开发 Web 应用等多项能力,真正做到“一句话,让 Al帮你完成复杂任务”。
更多推荐
所有评论(0)