Python 生成器·迭代器·with 上下文管理器
覆盖生成器/迭代器补充节、惰性、文件逐行读、with 上下文管理。一、补充节3 个高频内置 1 个表达式1. enumerate() —— 遍历带序号fruits [apple, banana, orange] for i, fruit in enumerate(fruits): print(i, fruit) # 0 apple / 1 banana / 2 orange 面试/实战处理数据集打序号、打日志第几条全用它。enumerate(列表, 1)序号从 1 起。2. zip() —— 多序列一对一配对names [Alice, Bob, Charlie] scores [85, 92, 78] for name, score in zip(names, scores): print(name, score) AI 常见问题列表配答案列表、文本配标签。3. 迭代器耗尽坑 ⚠️nums [1, 2, 3] it iter(nums) print(list(it)) # [1, 2, 3] ← 第一次正常 print(list(it)) # [] ← 第二次空了⚠️ 迭代器一次性跑完就废不像 list 能反复遍历。g fib(10)存下来跑一次就空想再用要重新fib(10)。4. 生成器表达式更短写法squares (x*x for x in range(10)) # () 生成器惰性省内存 squares_list [x*x for x in range(10)] # [] 列表立刻全算 圆括号()生成器惰性方括号[]列表全算。二、澄清迭代器 / 可迭代对象 / list 函数 三者关系身份能否 next()例子可迭代对象 iterable❌ 不能list、tuple、str、dict迭代器 iterator✅ 能iter(列表)、生成器、文件对象 flist() 函数—打包机把迭代器吸干返回新列表⚠️list不是迭代器没有 next。被掏空的是迭代器itlist()只是消费者它造出的新列表可反复遍历。⚠️next耗尽才报StopIterationlist()第二次返回[]不报错内部吞掉 StopIteration。三、惰性内存差异big_list [x*x for x in range(10_000_000)] # 立刻全算内存暴涨 big_gen (x*x for x in range(10_000_000)) # 一个不算现用现做 大数据AI 百万样本、超大日志用生成器惰性否则内存爆。小文件可用列表快速全拿。四、生成器逐行读大文件def read_lines(path): with open(path, r, encodingutf-8) as f: for line in f: yield line.strip() for line in read_lines(big.log): if ERROR in line: print(line)open()返回的文件对象是迭代器逐行吐加 yield 传递逐行能力内存只留一行。五、with 解决啥 —— 自动关资源with open(a.txt, r) as f: data f.read() # 退出自动 close报错也关 with 进门开门、出门自动锁门。管文件/数据库/网络端口/锁等资源的收尾。六、手写上下文管理器enter/exitclass MyFile: def __init__(self, path): self.path path def __enter__(self): self.f open(self.path, r) return self.f def __exit__(self, exc_type, exc_val, exc_tb): self.f.close() with MyFile(a.txt) as f: print(f.read())对照迭代器__iter__/__next__↔__enter__(进门)/__exit__(出门收尾)。⚠️__exit__三参数是异常信息异常时 Python 自动塞入有这仨就表示报错也走 exit。七、用 with 读文件实战with open(a.txt, r, encodingutf-8) as f: print(f.read()) with open(big.log, r, encodingutf-8) as f: for line in f: if ERROR in line: print(line) 实战别手写 MyFile直接用内置 open已带enter/exit。open开门拿遥控器f.xxx()用遥控器读with自动还。 焊点with自动关资源 文件对象是迭代器逐行惰性 读数据的标准姿势。八、易错点回顾已纠正误以为 list 是迭代器 → 实际 list 不能 next是 iterable。误以为文件对象 f 不能 next(f) → 实际 f 是迭代器能 next(f)。混淆两种 rangebooks[i]索引暴露内部vsfor _ in range(n)纯计数不矛盾。enumerate 拿序号元素不是序号函数。迭代器耗尽list 第二次返回 [] 不报错next 第二次才报 StopIteration。