python学习笔记 | 7.5、高级特性-迭代器
一、整体思路一句话看懂能放进 for 循环里遍历的叫 可迭代对象Iterable比如列表、字符串、字典、元组…能被 next () 一个个取数据的叫 迭代器Iterator迭代器 更高级的可迭代对象惰性计算用到才算不占内存所有迭代器都是可迭代对象但可迭代对象不一定是迭代器想用next()取普通列表 / 字符串用iter()转成迭代器就行二、具体说明1. 可迭代对象 Iterable定义能直接用for ... in ...循环遍历的东西。常见例子list 列表[1,2,3]str 字符串abcdict 字典{name:小明}tuple 元组(1,2,3)set 集合不能用 next ()直接用会报错2. 迭代器 Iterator定义能用for循环能用next()一个个取值惰性计算不一次性生成所有数据用到才算省内存常见例子生成器(x for x in range(10))用iter()转换后的可迭代对象取到最后没数据了会抛出StopIteration错误。3. 关键转换普通可迭代对象 → 迭代器迭代器对象 iter(普通可迭代对象)三、超简单实例直接复制运行 例子 1判断是不是可迭代对象# 导入判断工具 from collections.abc import Iterable # 列表是 print(isinstance([1,2,3], Iterable)) # True # 字符串是 print(isinstance(hello, Iterable)) # True # 数字不是 print(isinstance(123, Iterable)) # False 例子 2判断是不是迭代器from collections.abc import Iterator # 生成器是迭代器 print(isinstance((x for x in range(5)), Iterator)) # True # 列表不是迭代器 print(isinstance([1,2,3], Iterator)) # False 例子 3把列表变成迭代器重点# 普通列表可迭代但不是迭代器 my_list [10, 20, 30] # 转成迭代器 it iter(my_list) # 用 next() 一个个取 print(next(it)) # 10 print(next(it)) # 20 print(next(it)) # 30 # 再取就报错StopIteration没数据了 # print(next(it)) 例子 4for 循环的本质超重要# 我们平时写的 for x in [1,2,3]: print(x) # 它底层等价于 it iter([1,2,3]) while True: try: x next(it) print(x) except StopIteration: break四、终极口诀记住就够了能 for 循环 → 可迭代对象能 next () → 迭代器列表 / 字符串 / 字典 → 可迭代但不是迭代器iter () 一转 → 立刻变成迭代器迭代器惰性计算省内存能表示无限数据总结你只需要记住Iterable 能遍历Iterator 能一个个取惰性iter() 普通对象变迭代器next() 手动取迭代器里的值分割线练习题一、基础判断题每题10分共50分判断下列说法是否正确对的打√错的打×并简要说明理由小白可简单写。列表 [1,2,3] 是可迭代对象Iterable也是迭代器Iterator。 ❌️生成器 (x for x in range(3)) 可以用 next() 函数取值。 ✅️字符串 “python” 不是可迭代对象因为它不能用 next() 取值。 ❌️用 iter() 函数可以把字典 {“a”:1} 转换成迭代器。 ✅️所有可迭代对象Iterable都可以直接用 next() 函数取值。❌️ 二、实操选择题每题15分共30分请选出正确答案可先尝试运行代码小白建议复制到Python里跑一跑。下列代码运行后输出结果是C from collections.abc import Iterable, Iterator a (x for x in range(2)) print(isinstance(a, Iterable), isinstance(a, Iterator))A. True FalseB. False TrueC. True TrueD. False False下列代码运行后会输出什么 C❌️A✅️ my_str “abc” it iter(my_str) print(next(it), next(it))A. a bB. abcC. 报错D. a c三、实操编程题20分请写出代码完成以下需求小白可参考之前的实例一步步写定义一个列表 my_list [100, 200, 300, 400]判断它是否是可迭代对象、是否是迭代器#❌️ my_list [100, 200, 300, 400] print(my_list,isinstance(my_list,iterators.Iterable))#✅️ from collections.abc import Iterable, Iterator my_list [100, 200, 300, 400] print(列表内容,my_list) print(是否是可迭代对象,isinstance(my_list,Iterable)) print(是否是迭代器,isinstance(my_list,Iterator))2、将这个列表转换成迭代器from collections.abc import Iterable, Iterator my_list [100, 200, 300, 400] print(列表内容,my_list) print(是否是可迭代对象,isinstance(my_list,Iterable)) print(是否是迭代器,isinstance(my_list,Iterator)) # #❌️ # x for x in my_list: # print(x) it iter(my_list) # 这一行就是转换 print(\n转换后是不是迭代器, isinstance(it, Iterator))3、用 next() 函数依次取出迭代器中的所有值注意处理 StopIteration 错误可选做。# 1. 定义一个列表 my_list [100, 200, 300, 400]判断它是否是可迭代对象、是否是迭代器 from collections.abc import Iterable, Iterator my_list [100, 200, 300, 400] print(列表内容,my_list) print(是否是可迭代对象,isinstance(my_list,Iterable)) print(是否是迭代器,isinstance(my_list,Iterator)) # 2. 将这个列表转换成迭代器 # #❌️ # x for x in my_list: # print(x) #✅️ it iter(my_list) # 这一行就是转换 print(\n转换后是不是迭代器, isinstance(it, Iterator)) # 3. 用 next() 函数依次取出迭代器中的所有值注意处理 StopIteration 错误可选做。 # ❌️ # try: # print(x for x in next(it)) # except StopIteration: # print(结束) #✅️ while True: try: print(next(it)) except StopIteration: print(结束) break四、答案与解析一、基础判断题答案× 解析列表 [1,2,3] 是可迭代对象能for循环但不是迭代器不能直接用next()取值。√ 解析生成器是迭代器迭代器可以用next()一个个取值。× 解析字符串 “python” 是可迭代对象能for循环遍历只是不能直接用next()转成迭代器后才可以。√ 解析iter() 函数的作用就是把可迭代对象字典是可迭代对象转换成迭代器。× 解析只有迭代器能直接用next()普通可迭代对象比如列表、字符串不能直接用。二、实操选择题答案C 解析生成器既是可迭代对象能for循环也是迭代器能next()所以两个判断都是True。A 解析iter(my_str) 把字符串转成迭代器next(it) 依次取第一个、第二个字符就是 a 和 b。三、实操编程题答案两种写法小白选第一种即可基础写法不处理报错适合小白# 1. 定义列表并判断fromcollections.abcimportIterable,Iterator my_list[100,200,300,400]print(是否是可迭代对象,isinstance(my_list,Iterable))# 输出Trueprint(是否是迭代器,isinstance(my_list,Iterator))# 输出False# 2. 转换成迭代器ititer(my_list)# 3. 用next()取值print(next(it))# 100print(next(it))# 200print(next(it))# 300print(next(it))# 400# 再写一次next(it)会报错因为没有数据了进阶写法处理报错更规范fromcollections.abcimportIterable,Iterator my_list[100,200,300,400]# 判断print(是否是可迭代对象,isinstance(my_list,Iterable))print(是否是迭代器,isinstance(my_list,Iterator))# 转换迭代器ititer(my_list)# 循环取所有值处理报错whileTrue:try:print(next(it))exceptStopIteration:print(没有更多数据了)break总结做错的题目对应回去看之前的总结 - 判断题错了 → 再记“可迭代能for迭代器能next” - 选择题错了 → 复制代码到Python里运行看实际结果 - 编程题不会 → 参考实例先写判断再转迭代器最后用next()取值一步步来。分割线collections.abc是什么. 逐部分拆解核心from collections.abc import ...固定写法意思是 “从 Python 自带的collections.abc模块里拿出我们需要的工具”类比就像从家里的工具箱collections.abc模块里拿出尺子和剪刀需要的工具。Iterable是 “可迭代对象” 的判断工具用来判断一个对象比如列表、字符串能不能用for循环遍历。Iterator是 “迭代器” 的判断工具用来判断一个对象能不能用next()函数一个个取值。2. 为什么必须写这行代码没有这行代码直接用isinstance(my_list, Iterable)或isinstance(my_list, Iterator)Python 会报错不认识Iterable和Iterator。分割线巩固练习题巩固练习题迭代器专属2 道基础 1 道实操题目 1 判断对错list、str、dict 都是 Iterable但不是 Iterator。❌️答错了应该是✅️ 解析 列表、字符串、字典、元组、集合 全都能 for 循环 是Iterable 全都不能直接 next () 不是Iteratoriter(字符串)可以把字符串转为迭代器。✅️迭代器取完所有元素后继续next()不会报错。❌️题目 2 选择题下列哪一个天生就是迭代器 Iterator CA. [1,2,3]B. “hello”C. (x for x in range(5))D. {“a”:1}解析—答对了A 列表、B 字符串、D 字典都是可迭代对象 Iterable但不是迭代器C(x for x in range(5))生成器生成器 天生的迭代器 Iterator可以直接用next()题目 3 实操编程按步骤写代码定义字符串 s “python”判断 s 是否为 Iterable、是否为 Iterator用iter()转为迭代器循环 try-except next () 取出所有字符最后打印「取值完毕」## 题目 3 实操编程 from collections.abc import Iterable, Iterator # 按步骤写代码 # 1. 定义字符串 s python s python # 2. 判断 s 是否为 Iterable、是否为 Iterator print(s,isinstance(s,Iterable)) print(s,isinstance(s,Iterator)) # 3. 用 iter() 转为迭代器 it iter(s) # 4. 循环 try-except next () 取出所有字符最后打印「取值完毕」 while True: try: print(next(it)) except StopIteration: print(取值完毕) #补充 break分割线生成器和迭代器关系生成器一共就两种形式小白牢牢记住第一种生成器表达式括号写法语法把列表生成式的[]改成()# 列表生成式 lst [x for x in range(5)] # 生成器表达式第二种生成器 g (x for x in range(5))特点一行写完简单轻便天生就是迭代器惰性取值省内存第二种生成器函数带 yield语法函数里不写return写yielddef gen(): yield 1 yield 2 yield 3特点逻辑复杂、多步逻辑用它遇到yield暂停下次next()继续执行一句话总结生成器两种写法生成器表达式(x for x in ...)yield 生成器函数 函数里写 yield关键关系两种写法全部都是生成器所有生成器全部都是迭代器一、生成器两种形式 完整 极简示例形式 1生成器表达式小括号把列表推导式[]换成()就是生成器。# 列表一次性全部生成占内存 lst [x*2 for x in range(4)] # 生成器表达式惰性用到才算 g1 (x*2 for x in range(4)) print(next(g1)) print(next(g1))形式 2生成器函数含 yield普通函数用return生成器函数用yield。def g2(): yield 10 yield 20 yield 30 gen g2() print(next(gen)) print(next(gen))二、核心区别生成器表达式适合简单逻辑、一行搞定临时用、代码短yield 生成器函数适合复杂逻辑、循环、判断可以分段暂停、分步返回数据三、不变的结论必背两种写法都是生成器所有生成器都是迭代器都能用next()都具备惰性计算节省内存分割线