第 10 章 迭代器、生成器与函数式工具
10.1 可迭代对象与迭代器
可迭代对象(Iterable):实现了 __iter__ 的对象——list、str、dict、set、文件等,能用 for 遍历。
迭代器(Iterator):实现了 __iter__ 和 __next__ 的对象,是"一次性的取值流":
nums = [1, 2, 3]
it = iter(nums)
next(it)
next(it)
next(it)
next(it)
关键区别:
z = zip([1, 2], ["a", "b"])
list(z)
list(z)
10.2 生成器:惰性求值的利器
生成器是"自动实现了迭代器协议"的函数——含 yield 关键字的函数:
def countdown(n):
while n > 0:
yield n
n -= 1
gen = countdown(3)
next(gen)
next(gen)
for x in countdown(3):
print(x)
执行流程:调用生成器函数不执行函数体,返回生成器对象;每次 next() 执行到下一个 yield 暂停;return(或函数结束)触发 StopIteration。
为什么用生成器:内存
squares = [x * x for x in range(10_000_000)]
squares = (x * x for x in range(10_000_000))
sum(squares)
经典管道模式——多个生成器串成数据流水线:
def read_lines(path):
with open(path, encoding="utf-8") as f:
yield from f
def filter_errors(lines):
for line in lines:
if "ERROR" in line:
yield line
def parse(line):
return line.strip()[:80]
pipeline = (parse(l) for l in filter_errors(read_lines("huge.log")))
for item in pipeline:
print(item)
生成器的双向通信(了解)
def echo():
received = yield "ready"
while True:
received = yield f"got: {received}"
g = echo()
next(g)
g.send("hi")
yield from(委托)、throw()、close() 是进阶话题,初学掌握 yield 与生成器表达式即可。
10.3 函数式工具速览
map filter sorted 的 key
nums = [3, 1, 4, 1, 5, 9, 2, 6]
list(map(str, nums))
list(filter(lambda x: x > 3, nums))
sorted(nums, key=lambda x: -x)
import functools
@functools.cache
def fib(n):
return n if n < 2 else fib(n - 1) + fib(n - 2)
int2 = functools.partial(int, base=2)
int2("1010")
functools.reduce(lambda a, b: a * b, [1, 2, 3, 4])
import itertools
list(itertools.chain([1, 2], [3, 4]))
list(itertools.product("AB", "12"))
list(itertools.combinations([1,2,3], 2))
list(itertools.permutations([1,2], 2))
list(itertools.groupby(sorted(ws), key=len))
list(itertools.islice(itertools.count(), 3))
10.4 闭包与作用域回顾
闭包 = 内层函数记住外层函数的变量:
def make_multiplier(k):
def multiply(x):
return x * k
return multiply
double = make_multiplier(2)
triple = make_multiplier(3)
double(5)
triple(5)
闭包是装饰器、回调、延迟计算的基础(__closure__ 属性可查看捕获的变量)。
10.5 本章小结
for 的本质是 iter() + next() + StopIteration;
迭代器一次性耗尽,zip/map/文件对象 的返回值别二次消费;
含 yield 的函数是生成器:惰性、省内存、可搭管道;
functools.cache 先于手写缓存;itertools 组合数学问题先查它;
闭包记住外层变量,是装饰器的原理。
至此 Python 基础篇完结。进阶方向:并发(threading asyncio)、网络编程(requests socket)、测试(pytest)、Web 框架(FastAPI Flask)与数据分析(pandas NumPy)。