⚡ 19. 迭代器与生成器
本章概述
学习 Python 的迭代器和生成器,高效处理序列数据。 预计学习时间:50 分钟
19.1 什么是迭代
可以用 for 循环遍历的就是可迭代对象。
可迭代对象 Iterable
可以被迭代的对象,有 __iter__() 方法。
常见的可迭代对象:
- 列表、元组、字符串、字典、集合
- range 对象
- 文件对象
- 生成器
# 这些都是可迭代对象
for i in [1, 2, 3]: # 列表
pass
for c in "hello": # 字符串
pass
for k in {"a": 1}: # 字典
pass
for i in range(5): # range
pass判断是否可迭代
from collections.abc import Iterable
print(isinstance([1, 2, 3], Iterable)) # True
print(isinstance(123, Iterable)) # False19.2 迭代器 Iterator
迭代器是有 __next__() 方法的对象,一次返回一个值。
iter() 和 next()
lst = [1, 2, 3]
# iter() 获取迭代器
it = iter(lst)
# next() 获取下一个值
print(next(it)) # 1
print(next(it)) # 2
print(next(it)) # 3
print(next(it)) # StopIteration(没有更多元素了)for 循环的本质
for 循环的本质就是先获取迭代器,然后不断调用 next(),直到遇到 StopIteration。
# for 循环
for item in [1, 2, 3]:
print(item)
# 等价于
it = iter([1, 2, 3])
while True:
try:
item = next(it)
print(item)
except StopIteration:
break可迭代对象 vs 迭代器
| 类型 | 特点 | 示例 |
|---|---|---|
| 可迭代对象 | 有 __iter__(),可以被 for 循环 | 列表、字符串、字典 |
| 迭代器 | 有 __next__(),可以调用 next() | iter(列表)、生成器 |
关系
- 迭代器一定是可迭代对象
- 可迭代对象不一定是迭代器
- 用
iter()可以把可迭代对象变成迭代器
19.3 自定义迭代器
自己写一个类,实现 __iter__() 和 __next__() 方法。
示例:斐波那契数列迭代器
class Fibonacci:
def __init__(self, max_count):
self.max_count = max_count
self.count = 0
self.a = 0
self.b = 1
def __iter__(self):
return self # 返回迭代器本身
def __next__(self):
if self.count >= self.max_count:
raise StopIteration # 停止迭代
result = self.a
self.a, self.b = self.b, self.a + self.b
self.count += 1
return result
# 使用
fib = Fibonacci(10)
for num in fib:
print(num)19.4 生成器 Generator
生成器是一种特殊的迭代器,用 yield 关键字创建,更简洁。
生成器函数
def count_down(n):
while n > 0:
yield n # 暂停,返回值
n -= 1
# 调用生成器函数,返回生成器对象
gen = count_down(5)
print(gen) # <generator object count_down at ...>
# 可以用 for 循环遍历
for i in gen:
print(i)yield 的特点
yield vs return
return:函数结束,返回值yield:函数暂停,返回值,下次 next() 从暂停处继续
def demo():
print("开始")
yield 1
print("暂停后继续")
yield 2
print("再暂停后继续")
yield 3
print("结束")
gen = demo()
print(next(gen)) # 开始 \n 1
print(next(gen)) # 暂停后继续 \n 2
print(next(gen)) # 再暂停后继续 \n 3
print(next(gen)) # 结束 \n StopIteration19.5 生成器表达式
类似列表推导式,但用小括号,返回生成器。
基本用法
# 列表推导式(立即生成所有元素,占内存)
lst = [x**2 for x in range(10)]
print(lst) # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
# 生成器表达式(惰性计算,省内存)
gen = (x**2 for x in range(10))
print(gen) # <generator object <genexpr> at ...>
# 遍历生成器
for num in gen:
print(num)生成器的优势
- 省内存:一次只生成一个值,不用把所有数据都放内存里
- 惰性计算:用到的时候才计算
- 处理大数据时特别有用
带条件的生成器表达式
# 只生成偶数的平方
gen = (x**2 for x in range(10) if x % 2 == 0)19.6 生成器的方法
send() 发送数据
def echo():
while True:
msg = yield # 接收发送的值
print(f"收到:{msg}")
gen = echo()
next(gen) # 启动生成器,停在yield处
gen.send("你好") # 收到:你好
gen.send("世界") # 收到:世界throw() 抛出异常
def demo():
try:
yield 1
yield 2
yield 3
except ValueError:
print("捕获到ValueError")
gen = demo()
next(gen) # 1
gen.throw(ValueError) # 捕获到ValueErrorclose() 关闭生成器
def demo():
try:
yield 1
yield 2
finally:
print("生成器关闭了")
gen = demo()
next(gen) # 1
gen.close() # 生成器关闭了19.7 yield from
从另一个生成器中 yield 所有值。
基本用法
def inner():
yield 1
yield 2
yield 3
def outer():
# 方式1:手动循环
# for x in inner():
# yield x
# 方式2:用 yield from
yield from inner()
for num in outer():
print(num)应用场景
- 生成器嵌套
- 协程(高级话题)
19.8 生成器的应用场景
1. 处理大数据
# 读取大文件,逐行处理,不占内存
def read_large_file(file_path):
with open(file_path, "r", encoding="utf-8") as f:
for line in f:
yield line.strip()
for line in read_large_file("big_file.txt"):
# 处理每一行
pass2. 无限序列
# 无限的斐波那契数列
def fibonacci():
a, b = 0, 1
while True:
yield a
a, b = b, a + b
fib = fibonacci()
for i in range(10):
print(next(fib))3. 管道(流水线)
def numbers():
for i in range(10):
yield i
def square(nums):
for n in nums:
yield n ** 2
def even(nums):
for n in nums:
if n % 2 == 0:
yield n
# 流水线:生成数字 → 平方 → 过滤偶数
result = even(square(numbers()))
for num in result:
print(num)19.9 迭代工具 itertools
Python 标准库提供了很多迭代工具。
常用函数
import itertools
# count:无限计数
for i in itertools.count(10, 2): # 从10开始,步长2
if i > 20:
break
print(i)
# cycle:无限循环
for i, c in enumerate(itertools.cycle("ABC")):
if i >= 6:
break
print(c)
# repeat:重复
for i in itertools.repeat("hello", 3):
print(i)
# chain:连接多个可迭代对象
for i in itertools.chain([1, 2], [3, 4], [5, 6]):
print(i)
# product:笛卡尔积
for a, b in itertools.product("AB", [1, 2]):
print(a, b)
# permutations:排列
for p in itertools.permutations([1, 2, 3], 2):
print(p)
# combinations:组合
for c in itertools.combinations([1, 2, 3], 2):
print(c)itertools 很强大
处理迭代相关的问题时,先看看 itertools 有没有现成的。
🔗 相关章节
📝 我的笔记
在这里记录你的理解、疑问和练习代码
# 你的练习代码
✅ 本章检查清单
- 理解可迭代对象和迭代器的概念
- 会使用 iter() 和 next()
- 会自定义迭代器
- 掌握生成器函数和 yield
- 会使用生成器表达式
- 了解生成器的 send/throw/close 方法
- 了解 yield from
- 知道生成器的应用场景
- 了解 itertools 模块