【高级】Python迭代器(__iter__())与生成器(__next__()):小白也能看懂的内存高手解密!

1 迭代器与生成器

1.1 迭代器(Iterator)

在 Python 中,迭代器是一个可以遍历对象的工具。常见的迭代对象包括列表、元组、字符串等。迭代器对象需要实现两个方法:iter() 和 next()。
iter():返回迭代器对象本身。
next():返回序列的下一个元素,当没有更多元素时抛出 StopIteration 异常。

**使用场景:**迭代器通常用于处理大型数据集或流数据,因为它一次只处理一个数据,而不是将整个数据集加载到内存中。适合处理大文件、生成大量数据等情况。

# 自定义一个迭代器类来生成一个递增序列
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:
            self.current += 1
            return self.current - 1# 使用迭代器遍历生成的序列
my_iter = MyIterator(0, 5)
for num in my_iter:
    print(num)

在这里插入图片描述

解释:

• 这个代码自定义了一个迭代器类 MyIterator,用于生成一个从 start 到 end 的递增数字序列。
• 当序列结束时,抛出 StopIteration 异常,表示迭代结束。

1.2 生成器(Generator)

生成器是一种特殊的迭代器,它通过 yield 关键字来逐个产生值,而不是一次性返回所有值。这使得生成器非常高效,尤其在处理大量数据时。
**• yield:**在函数中暂停执行,返回一个值,下次调用时继续从暂停的地方执行。
**使用场景:**生成器通常用于惰性求值(lazy evaluation)的场景,尤其是在需要处理大量数据或无限序列时,非常节省内存。

# 定义一个生成器函数,用来生成一个从0到指定范围的偶数序列
def even_numbers(limit):
    num = 0
    while num < limit:
        if num % 2 == 0:
            yield num  # 每次遇到 yield 返回一个值,并暂停
        num += 1# 使用生成器函数生成偶数
for even in even_numbers(10):
    print(even)

在这里插入图片描述

解释:

• yield 的作用是让函数在返回一个值后暂停执行,等待下一次调用后继续执行。
• 每次调用生成器会从上一次暂停的地方继续执行,直到到达 limit 为止。

生成器表达式

生成器表达式与列表推导式相似,但它不生成完整的列表,而是生成器对象,用于逐个产生值。

# 生成器表达式,创建一个生成1到10的平方数序列
gen_exp = (x**2 for x in range(1, 11))# 逐个打印生成器中的值
for value in gen_exp:
    print(value)

在这里插入图片描述
解释:
• 生成器表达式使用 (),类似于列表推导式,但它不会一次性生成所有结果,而是按需逐个生成。

2 迭代器与生成器

我们来构建一个工作中可能会遇到的小型项目案例,结合迭代器和生成器处理大文件和实时数据流。在实际工作中,经常需要处理海量数据,比如读取一个大的日志文件或者不断处理网络请求中的数据流。

2.1 场景:日志文件分析系统

假设你有一个巨大的服务器日志文件,文件很大,无法一次性加载到内存中。你需要逐行读取日志文件,分析其中的错误记录并做统计。这个任务可以通过迭代器来完成。

迭代器实现:逐行读取日志文件
我们可以使用一个自定义的迭代器,来逐行读取日志文件并处理。

# 定义一个迭代器类,用来逐行读取大型日志文件
class LogFileIterator:
    def __init__(self, file_path):
        self.file = open(file_path, 'r', encoding='utf-8')  # 打开文件
        self.line_number = 0def __iter__(self):
        return self
​
    def __next__(self):
        self.line_number += 1
        line = self.file.readline()  # 逐行读取文件
        if not line:  # 当读取到文件末尾时,停止迭代
            self.file.close()
            raise StopIteration
        return self.line_number, line.strip()  # 返回行号和行内容# 创建一个日志文件的迭代器对象
log_iter = LogFileIterator('server_log.txt')# 通过迭代器逐行分析日志文件内容
for line_number, line_content in log_iter:
    if 'ERROR' in line_content:  # 查找包含 'ERROR' 的行
        print(f"第 {line_number} 行出现错误: {line_content}")

在这里插入图片描述
详细注释:
• LogFileIterator 类实现了一个日志文件迭代器,它逐行读取文件内容,每次读取一行,返回行号和行内容。
iter() 返回自身,以便支持迭代功能。
next() 是迭代器的核心逻辑,逐行读取文件,当没有内容时,抛出 StopIteration 来结束迭代。
• 在实际的使用中,我们通过迭代器对象 log_iter 来逐行处理日志文件,找出含有 ERROR 的行并打印。

2.2 生成器实现:实时日志监控

假设你正在处理实时日志流,比如从服务器上实时获取日志数据,并且需要监控日志中的错误信息。此时可以使用生成器来动态生成日志数据。

import time
​
# 定义一个生成器函数,用于模拟实时日志流
def log_stream():
    # 模拟日志条目
    logs = [
        "INFO: User 123 logged in",
        "ERROR: Failed to connect to database",
        "WARNING: Low disk space",
        "INFO: User 456 logged out",
        "ERROR: Timeout while fetching data"
    ]
    for log in logs:
        time.sleep(1)  # 模拟实时日志的产生延迟
        yield log  # 每次产生一条日志记录# 处理生成器产生的实时日志流
for log_entry in log_stream():
    if 'ERROR' in log_entry:  # 处理实时日志中的错误信息
        print(f"实时监控到错误: {log_entry}")

在这里插入图片描述
详细注释:
• log_stream() 函数是一个生成器,它模拟了一个实时日志流,每次生成一条日志数据。
• 使用 yield 关键字让生成器在每次产生一条日志后暂停,等待下次继续生成。
• 在循环中,通过 for log_entry in log_stream() 动态获取日志数据,并对包含 ERROR 的日志条目进行处理。

小结

通过迭代器处理大型文件和生成器处理实时数据流是 Python 中的常见工作场景。迭代器适用于一次性不能加载的大数据集,而生成器则在处理实时数据时尤其高效。两者都是高效处理数据的利器,能够在不同场景下大幅度提升程序性能。

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值