Python3 迭代器与生成器
迭代器(iterator)是"按需逐个取出数据"的对象;生成器(generator)是 Python 实现惰性求值的主要方式。它们让程序边算边取、不必一次性把数据全放进内存,是处理大数据时的利器。
可迭代对象与迭代器
能被 for 遍历的对象(列表、元组、字典、字符串等)叫可迭代对象;iter() 得到迭代器,next() 逐个取值:
nums = [1, 2, 3] # 可迭代对象
it = iter(nums) # 迭代器
print(next(it)) # 输出:1
print(next(it)) # 输出:2
print(next(it)) # 输出:3
# print(next(it)) # 报错:StopIteration(取完了)
StopIteration 与 for 的本质
迭代器取尽后再 next 抛 StopIteration。for 的本质就是不断 next,捕获该异常后结束:
it = iter([1, 2])
while True:
try:
x = next(it)
print(x, end=" ") # 输出:1 2
except StopIteration:
break # 取完自动跳出
迭代器只能前进
迭代器像"单向指针",取过的元素不保留,不能回头,也不能用下标随机访问。
生成器函数 yield
函数体内出现 yield 即生成器函数:每次执行到 yield 返回值并暂停,下次 next 从暂停处继续:
def count_down(n):
while n > 0:
yield n # 产出并暂停
n -= 1
for x in count_down(3):
print(x, end=" ") # 输出:3 2 1
生成器表达式
列表推导式的方括号换成圆括号即生成器表达式,惰性求值、不占内存:
g = (x * x for x in range(3))
print(g) # 输出:<generator object ...>
print(list(g)) # 输出:[0, 1, 4](一次性消费)
节省内存
生成器一次只产生一个值,处理超大序列时内存占用几乎不变:
# 前 100 万个数的平方和,生成器版几乎不占内存
total = sum(x * x for x in range(1000000))
print(total) # 输出:333332833333500000
range/map 的惰性特点
Python 3 中 range()、map()、filter() 返回惰性对象,查看内容用 list() 转换:
r = range(3)
print(r) # 输出:range(0, 3)
m = map(str, [1, 2])
print(list(m)) # 输出:['1', '2']
小结:迭代器与生成器把"一批数据"变成"一个个按需产出",配合惰性对象显著降低内存占用,是高效处理大数据的基础。