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 抛 StopIterationfor 的本质就是不断 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']

小结:迭代器与生成器把"一批数据"变成"一个个按需产出",配合惰性对象显著降低内存占用,是高效处理大数据的基础。

笔记加载中…