Skip to content

上下文管理器与标准库

with 协议、contextlib、functools/collections/itertools。

Updated View as Markdown
For humans

上下文管理器与标准库

面试主线两块: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 就够。

面试追问

  1. with 语句怎么工作? enter 进入返回资源,exit 退出清理,异常也会走 exit。保证资源释放
  2. contextmanager 怎么写? yield 前是进入逻辑,yield 后是退出逻辑,try/finally 保证清理
  3. defaultdict 和 Counter 的区别? defaultdict 是缺键给默认值;Counter 专门计数,有 most_common
  4. deque 什么时候用? 双端插入删除 O(1),list 头部操作 O(n)。队列、滑动窗口
  5. itertools 的特点? 全惰性,内存友好。groupby 要排序后相邻才分组
Navigation

Type to search…

↑↓ navigate↵ selectEsc close