news 2026/5/27 3:31:00

AI_Python基础-6.迭代器与生成器

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
AI_Python基础-6.迭代器与生成器

Python 迭代器与生成器

标签: #Python #迭代器 #生成器 #yield #延迟计算
学习周期:1 天 | 核心目标:理解迭代协议,掌握生成器实现延迟计算,对比列表推导式与生成器表达式的内存差异


3.2 迭代器与生成器

迭代器与生成器是 Python 中高效处理序列数据的核心工具,核心优势是延迟计算(惰性求值)—— 不一次性生成所有数据,而是按需生成,大幅节省内存(尤其适合处理海量数据)。


3.2.1 可迭代对象(__iter__)与迭代器(__next__

核心概念对比
类型核心特征关键方法示例
可迭代对象能被for循环遍历,可生成迭代器__iter__():返回迭代器liststrtupledictset
迭代器可逐个返回元素,可记录遍历位置,只能遍历一次__next__():返回下一个元素;__iter__():返回自身iter(list)、文件对象、生成器对象
判断可迭代对象和迭代器
fromcollections.abcimportIterable,Iterator lst=[1,2,3]print(isinstance(lst,Iterable))# True(可迭代)print(isinstance(lst,Iterator))# False(不是迭代器)it=iter(lst)# 获取迭代器print(isinstance(it,Iterator))# True
手动使用迭代器
lst=[1,2,3]it=iter(lst)# 获取迭代器print(next(it))# 1print(next(it))# 2print(next(it))# 3# print(next(it)) # StopIteration 异常
for循环的工作原理
# for 循环等价于:it=iter(可迭代对象)whileTrue:try:value=next(it)# 执行循环体exceptStopIteration:break
自定义迭代器
classMyIterator:def__init__(self,start,end):self.current=start self.end=enddef__iter__(self):returnselfdef__next__(self):ifself.current>self.end:raiseStopIteration temp=self.current self.current+=1returntemp my_iter=MyIterator(1,3)fornuminmy_iter:print(num)# 1, 2, 3# 再次遍历(迭代器已耗尽,无输出)fornuminmy_iter:print(num)
易错点说明
  • 可迭代对象 ≠ 迭代器:可迭代对象需要通过iter()转换为迭代器才能手动遍历。
  • 迭代器只能遍历一次:遍历结束后指针停在最后,无法重置,需重新创建迭代器。
  • for循环的底层逻辑:先调用iter(可迭代对象)生成迭代器,再循环调用next(),直到捕获StopIteration异常,自动终止循环。

3.2.2 生成器函数(yield)—— 延迟计算,节省内存

生成器是一种特殊的迭代器,使用yield关键字定义。生成器函数在每次调用next()时执行到yield暂停并返回一个值,下次调用从暂停处继续。

核心特性
  • 延迟计算:只在需要时生成值,节省内存。
  • 状态保持:函数内的局部变量在每次yield之间保持。
  • 无限序列:可以表示无限大的序列(如斐波那契数列)。
基本用法
defmy_generator(start,end):current=startwhilecurrent<=end:yieldcurrent current+=1gen=my_generator(1,3)# 创建生成器对象,函数体不会立即执行print(type(gen))# <class 'generator'>print(isinstance(gen,Iterator))# True# 手动遍历print(next(gen))# 1print(next(gen))# 2print(next(gen))# 3# print(next(gen)) # StopIteration# for 循环遍历(推荐)fornuminmy_generator(1,3):print(num)# 1, 2, 3
生成器实现斐波那契数列(节省内存)
deffibonacci(limit):a,b=0,1whilea<limit:yielda a,b=b,a+bfornuminfibonacci(100):print(num,end=" ")# 0 1 1 2 3 5 8 13 21 34 55 89
生成器的进阶方法(sendclose
defecho():whileTrue:received=yieldprint(f"收到:{received}")gen=echo()next(gen)# 预激生成器,执行到第一个 yieldgen.send("Hello")# 收到:Hellogen.send("World")# 收到:Worldgen.close()# 关闭生成器
应用场景
  • 处理海量数据(如读取超大文件、生成百万级随机数),避免内存溢出。
  • 惰性计算场景:批量处理数据,不需要一次性获取所有结果。
  • 替代列表推导式:当数据量较大时,用生成器替代列表推导式。

3.2.3 生成器表达式

生成器表达式类似于列表推导式,但使用圆括号()而不是方括号[]。它返回一个生成器对象,而不是一次性创建列表,适合处理大量数据。

语法
(expressionforiteminiterableifcondition)
示例与对比
# 列表推导式:立即生成所有值,占用内存squares_list=[x**2forxinrange(10)]print(squares_list)# [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]# 生成器表达式:延迟计算,不占内存squares_gen=(x**2forxinrange(10))print(squares_gen)# <generator object <genexpr> at 0x...>forvalinsquares_gen:print(val,end=" ")# 0 1 4 9 16 25 36 49 64 81# 一次性转换为列表(失去生成器的优势)squares_list2=list(x**2forxinrange(10))
内存对比
importsys# 列表推导式:立即分配内存list_comp=[xforxinrange(1000000)]print(sys.getsizeof(list_comp))# 约 8 MB# 生成器表达式:几乎不占内存gen_exp=(xforxinrange(1000000))print(sys.getsizeof(gen_exp))# 约 104 字节
与高阶函数配合
# 计算 1 到 1e6 的平方和(无需创建巨大列表)total=sum(x**2forxinrange(1,1000001))print(total)# 找出 1 到 1e6 中能被 7 整除的最大数max_val=max(xforxinrange(1,1000001)ifx%7==0)print(max_val)
实战场景:逐行读取大文件
defread_large_file(file_path):return(line.strip()forlineinopen(file_path,"r",encoding="utf-8"))# 使用:按需读取,内存占用极低forlineinread_large_file("large_file.txt"):print(line)# 逐行处理
易错点说明
  • 生成器表达式的圆括号不能省略,否则会变成普通表达式。
  • 生成器表达式也是“一次性的”,遍历结束后无法重复使用,需重新定义。
  • 数据量小且需要多次访问时用列表推导式;数据量大且只需遍历一次时用生成器表达式。

3.2.4 迭代器、生成器与列表推导式的选择

场景推荐方案原因
数据量小,需要多次遍历列表推导式值已存储在内存中,访问快
数据量大,只需遍历一次生成器表达式或生成器函数节省内存,延迟计算
需要复杂逻辑控制生成器函数(yield可暂停、保持状态,代码清晰
需要向生成器发送数据生成器函数 +send()双向通信

📚 学习资料(Obsidian 可直接收藏)

  • 官方文档
    Python 迭代器协议
    Python 生成器
    yield 表达式
    生成器表达式

  • 中文教程
    廖雪峰 - 迭代器与生成器
    菜鸟教程 - 迭代器与生成器

  • 视频推荐
    Python 生成器详解(B站)


🎯 学习建议(1 天计划)

  1. 上午:理解可迭代对象与迭代器的区别,手动实现__iter____next__,练习生成器函数(yield)。
  2. 下午:掌握生成器表达式,对比列表推导式的内存占用,完成实战练习(大文件读取、无限序列生成)。

✅ 核心要点总结

  1. 可迭代对象:实现了__iter__(),返回迭代器。常见的有liststrdict等。
  2. 迭代器:实现了__iter__()__next__(),只能遍历一次。for循环依赖迭代协议。
  3. 生成器函数:使用yield的函数,调用时返回生成器对象(属于迭代器),支持延迟计算和状态保持。
  4. 生成器表达式:类似列表推导式但使用(),返回生成器对象,适合大数据量处理。
  5. 内存优势:生成器和生成器表达式不一次性存储所有元素,处理大数据集时能显著降低内存占用。
  6. 一次性特点:生成器和迭代器都只能遍历一次,无法重置。

练习题(自测)

  1. 定义一个可迭代对象Fibonacci,使用__iter____next__实现斐波那契数列的前n项。
  2. 编写生成器函数read_large_file(file_path),逐行读取大文件(模拟),每次yield一行。
  3. 使用生成器表达式找出 1 到 100000 中所有能被 13 整除的数,并计算它们的和(不使用列表)。
  4. 实现一个无限生成器cycle(iterable),无限循环返回可迭代对象中的元素(如cycle('AB')输出A B A B ...)。
  5. 写一个生成器primes(),无限产生素数(使用埃拉托斯特尼筛法或试除法)。

建议在 Jupyter Notebook 或本地环境中运行,比较生成器和列表推导式的内存差异。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/27 3:29:58

Linux 开机自启配置全实战(3种方式,CentOS7+通用)

一、前言服务器重启后&#xff0c;业务脚本、自定义程序、第三方服务会全部中断&#xff0c;想要程序开机自动运行&#xff0c;必须配置开机自启。本文讲解生产环境最常用3种开机自启方案&#xff0c;覆盖系统服务自启、脚本自启、自定义服务文件&#xff0c;零基础直接上手&am…

作者头像 李华
网站建设 2026/5/27 3:28:00

别再让电脑‘睡死’:深入解决Windows WOL远程唤醒失效的终极指南

彻底根治Windows远程唤醒失效&#xff1a;从底层原理到高阶配置实战 深夜加班时突然需要访问家中电脑&#xff0c;却发现远程唤醒功能再次"罢工"——这恐怕是许多技术爱好者都遭遇过的窘境。不同于常规教程只讲解基础设置&#xff0c;本文将直击WOL&#xff08;Wake…

作者头像 李华
网站建设 2026/5/27 3:25:04

CVE复现 | CVE-2026-20841漏洞复现

注&#xff1a;文章涉及内容仅供安全研究与学习之用&#xff0c;若将文章相关内容做其他用途&#xff0c;由使用者承担全部法律及连带责任&#xff0c;作者及发布者不承担任何法律及连带责任。信息及工具收集于互联网&#xff0c;真实性及安全性自测&#xff01;&#xff01; …

作者头像 李华
网站建设 2026/5/27 3:20:58

STM32 DFU文件生成避坑指南:为什么你的hex文件总转换失败?

STM32 DFU文件生成避坑指南&#xff1a;为什么你的hex文件总转换失败&#xff1f;当你在深夜调试STM32项目&#xff0c;终于编译通过生成了hex文件&#xff0c;却在最后一步DFU转换时遭遇"Invalid file"的红色警告——这种崩溃感每个嵌入式开发者都懂。本文将彻底解析…

作者头像 李华
网站建设 2026/5/27 3:20:58

ai 中转站0.1元卖你12块 各云计算平台 50倍利润 用脚本就看出来有没 黑我们 除了隐私 还有中间商差价 DeepSeek-TUI reasonix claude都用不了缓存命中

# 除了隐私有没盗用 答案是 肯定盗用 他们的利润高达 50倍 . 目前只发现中转站 不知道 各大云计算平台比如 ** 这些大平台有没这么做 所以有隐私数据 绝对不建议用中转站 因为会跑路 ,就是你充钱了 它跑了 ## 怎么中间商差价 导致 模型根本不太聪明的样子 1.偷换模型 ⚠️…

作者头像 李华
网站建设 2026/5/27 3:20:10

扫地机器人行业 企业篇-小米/米家

小米依托生态链模式切入扫地机器人领域,以高性价比和IoT生态联动为核心竞争力。小米生态链内扫地机业务曾依赖石头科技和追觅两家生态链企业代工,两家独立后,2023年小米生态链部架构调整,将扫地机单独设为一个部门,加大自研投入。 公司性质为港交所上市公司,小米集团整体…

作者头像 李华