Python 面试题

Python装饰器:原理、functools.wraps、带参数

讲讲装饰器原理。写一个@retry(times=3)。

为什么面试官会问这道题

会用@是中级Python底线;带参数装饰器能过滤掉"只会用不懂原理"的。

如何回答

  1. 1

    `@decorator\ndef f:...`等价于`f = decorator(f)`。decorator是任意接受callable返回callable的东西。

  2. 2

    典型:`def deco(fn): def wrapper(*a, **kw): ...; return fn(*a, **kw); return wrapper`。

  3. 3

    在wrapper上加`functools.wraps(fn)`保留__name__、__doc__、__wrapped__——否则help()和日志就乱了。

  4. 4

    带参数装饰器:三层——最外层接参数、返回真正的装饰器。

  5. 5

    类装饰器:__init__捕获fn、__call__让实例可调用。

参考回答示例

装饰器就是任意"接受函数返回可调用"的东西。`@foo`在`def f()`上面等价于`f = foo(f)`。套路:外层函数里定义wrapper,wrapper在调用原函数前后加逻辑,返回wrapper。永远在wrapper上加`@functools.wraps(fn)`——否则__name__、__doc__、trace都会变成"wrapper"。`@retry(times=3)`要三层:retry(times)返回decorator(fn),decorator返回wrapper(*a, **kw)在其中循环捕获异常。带参数装饰器绕晕人的点:最外层拿到参数,它的返回值才是真正的装饰器。

实用技巧

  • @functools.lru_cache是内置好装饰器——零TTL内存记忆化。

  • 异步函数要写异步感知的装饰器:wrapper必须async def并await fn(...)。

  • 即答侠背了三层带参模板+functools.wraps位置正确。

常见问题

忘加functools.wraps会怎样?

被装饰函数的名字和docstring会丢,inspect/sphinx/调试器看到的都是wrapper。讨厌但不致命。

类装饰器 vs 函数装饰器?

类装饰器用self存状态更清晰。函数装饰器更轻。功能上等价。

面试时担心忘词?即答侠实时助你

即答侠 AI 实时监听面试对话,自动识别问题并即时生成回答建议——无感辅助,让你从容应对每一道题。

免费试用即答侠