🐍Python 函数与面向对象

异常与上下文管理器

面试回答

常见问法

  • try/except/else/finally 四个分支分别什么时候执行?
  • with 语句背后做了什么?__enter____exit__ 怎么写?
  • 怎么自定义异常?什么时候该抛、什么时候该吞?
  • contextlibcontextmanagerExitStacksuppress 分别用在什么场景?

回答

待补充:从「资源生命周期管理」和「错误传播语义」两条主线讲,强调「EAFP(easier to ask forgiveness than permission)」风格在 Python 里为什么主流。

追问

  • except Exception as e 和裸 except 有什么危险差异?
  • 异常链 raise X from Y 是什么?
  • __exit__ 返回 True 会发生什么?
  • 异步 with(async with)怎么写?

原理展开

  • 四分支执行顺序:try → [except|else] → finally
  • 上下文管理器协议:__enter__ 返回资源,__exit__(exc_type, exc_val, tb) 清理
  • @contextmanager 装饰器:用生成器写 context manager
  • ExitStack:动态组合多个 context manager
  • 异常链:raise NewError() from old_error,保留 __cause__
  • contextlib.suppress:替代「空 except」的干净写法

易错点

  • except: 吞掉 KeyboardInterruptSystemExit
  • finallyreturn 会覆盖 try 里的返回值
  • 自定义 __exit__ 返回 True,无声吞异常
  • 忘记 with 本质是「编译器生成 try/finally」,而不是语法糖那么简单

记忆技巧

  • 四分支口诀:try 跑 / except 接 / else 顺利 / finally 必走
  • with 本质:进入拿资源,退出必清理,异常不影响清理
  • EAFP 口诀:先做再说,错了再抓,比事前检查更 Pythonic