一、迭代器的基本概念、实现方式及使用场景

(一)基本概念

迭代器(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)展示迭代器的一次性特性。

(三)使用场景

  1. 处理大量数据:当数据量很大时,使用迭代器可以避免一次性将所有数据加载到内存中,而是按需生成数据,节省内存空间。例如,读取一个几 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 是数据处理函数
  1. 自定义可迭代对象:当我们需要创建一个自定义的序列类型,并且希望它能够被迭代时,就可以通过实现迭代器来实现。比如自定义一个日期迭代器,用于遍历一段时间内的日期。

示例(日期迭代器):

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语句时,函数会暂停并返回值,下次调用时从暂停处继续执行(保留局部变量的状态)。可以把生成器看作是 “按需生产数据的工厂”,只有在被请求时才会生成下一个值。

(二)实现方式

生成器有两种实现方式:

  1. 生成器函数:在函数中使用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 后继续执行)
  1. 生成器表达式:类似于列表推导式,但使用圆括号()而不是方括号[],它会返回一个生成器对象。

示例(生成器表达式与列表推导式的对比):

# 生成器表达式(仅定义,不计算)
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]

突出生成器 “延迟计算” 的特性。

(三)使用场景

  1. 处理大数据流:和迭代器类似,生成器也适合处理大量数据或无限数据流,因为它不会一次性生成所有数据,而是按需生成,能有效节省内存。例如,生成无限的斐波那契数列。

    示例(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 模型
    
  2. 简化迭代器代码:当我们需要实现一个迭代器时,如果使用生成器来实现,代码会更加简洁易懂。相比显式实现__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)
    
  3. 简单的协程功能:生成器可以通过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自动实现迭代协议,代码更简洁,是处理大数据和简化迭代逻辑的首选。

记住一个简单的判断:如果能用几行代码实现迭代逻辑,优先用生成器;如果需要复杂的状态管理或自定义行为,再考虑手动实现迭代器。掌握这两个工具,能让你的数据处理代码更高效、更易维护。

Logo

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

更多推荐