上下文管理器与标准库
面试主线两块:with 语句的机制与写法,以及三个高频标准库模块的正确用法。标准库答得好是加分项,体现工程经验。
with 与上下文管理器
with open("f.txt") as f: # 文件自动关闭, 异常也关闭
data = f.read()协议:进入执行 __enter__(返回值绑定给 as),退出执行 __exit__(负责清理,异常时也会调用)。
class ManagedFile:
def __enter__(self):
return self
def __exit__(self, exc_type, exc_val, exc_tb):
self.close() # 正常/异常都会执行
return False # False: 异常继续传播; True: 吞掉异常contextlib.contextmanager:yield 写法,把生成器变成上下文管理器:
from contextlib import contextmanager
@contextmanager
def managed():
print("进入")
try:
yield value # yield 前是 __enter__, 后是 __exit__
finally:
print("退出") # 保证清理ExitStack:动态管理不确定数量的上下文:
with ExitStack() as stack:
for path in files:
stack.enter_context(open(path))functools:函数工具箱
| 工具 | 用途 |
|---|---|
lru_cache |
缓存函数结果(见设计模式篇),注意参数可哈希 |
partial |
固定部分参数生成新函数(带参工厂) |
wraps |
装饰器保留元信息 |
cache |
3.9+ 无上限版 lru_cache |
reduce |
累积计算(可读性差,多数场景用循环替代) |
collections:容器增强
| 工具 | 替代 | 场景 |
|---|---|---|
defaultdict |
dict | 缺键自动给默认值(分组统计) |
Counter |
dict 计数 | 词频统计,most_common(n) |
deque |
list | 双端操作 O(1),队列/滑动窗口 |
namedtuple |
tuple | 带名字的不可变记录 |
OrderedDict |
dict | 需要显式顺序语义(dict 已保序,用得少了) |
itertools:迭代器工厂
| 工具 | 用途 |
|---|---|
chain |
拼接多个可迭代对象 |
groupby |
相邻分组(要先排序) |
islice |
迭代器切片 |
product |
笛卡尔积 |
combinations / permutations |
组合/排列 |
count / cycle |
无限序列(配合 islice 取前 N) |
itertools 全部惰性,处理大数据的正确姿势;面试提 chain/groupby 就够。
面试追问
- with 语句怎么工作? enter 进入返回资源,exit 退出清理,异常也会走 exit。保证资源释放
- contextmanager 怎么写? yield 前是进入逻辑,yield 后是退出逻辑,try/finally 保证清理
- defaultdict 和 Counter 的区别? defaultdict 是缺键给默认值;Counter 专门计数,有 most_common
- deque 什么时候用? 双端插入删除 O(1),list 头部操作 O(n)。队列、滑动窗口
- itertools 的特点? 全惰性,内存友好。groupby 要排序后相邻才分组