当前位置:首页>python>十个 Python 技术面试必考的装饰器题目,搞懂这些,面试官直点头.

十个 Python 技术面试必考的装饰器题目,搞懂这些,面试官直点头.

  • 2026-09-08 05:21:02
十个 Python 技术面试必考的装饰器题目,搞懂这些,面试官直点头.

面试装饰器时,很多人只会背语法糖。我跟几个大厂面试官聊过,他们真正想听的,是你对函数、闭包、作用域的理解。下面十道题,全是硬骨头。

1. 一个函数被多个装饰器装饰,执行顺序是怎样的

代码写上

@decorator_a 

@decorator_b

def myfunc():

   pass

实际执行是 myfunc = decorator_a(decorator_b(myfunc))。离函数最近的装饰器先处理,然后一层层向外包。面试官想看你能不能说出这个栈结构。

2. 写一个装饰器,统计函数每次调用的时间

核心是记录调用前后的时间差。注意不能用全局变量,要用闭包保存起始时间。实现时记得用 functools.wraps 保留原函数信息,否则元信息会丢失。

import time 

from functools import wraps

def timer(func):

   @wraps(func)

   def wrapper(args, kwargs):

       start = time.time()

       result = func(args, kwargs)

       print(f'{func.__name__} 耗时 {time.time()-start:.2f} 秒')

       return result

   return wrapper

3. 如何给装饰器传参数

需要三层嵌套。最外层接收参数,中间层接收函数,内层处理逻辑。

def repeat(n): 

   def decorator(func):

       @wraps(func)

       def wrapper(args, kwargs):

           for _ in range(n):

               func(args, kwargs)

       return wrapper

   return decorator

@repeat(3)

def say_hello():

   print('你好')

4. 类装饰器怎么写

实现 __call__ 方法,让类的实例可调用。类装饰器的好处是可以保存状态。

class CountCalls: 

   def __init__(self, func):

       self.func = func

       self.count = 0

   def __call__(self, args, kwargs):

       self.count += 1

       print(f'第 {self.count} 次调用')

       return self.func(args, kwargs)

5. 装饰器如何保留原函数的元信息

很多人的装饰器会覆盖函数名和文档。用 @wraps(func) 手动复制 __name__、__doc__、__module__。这是面试高频点。

6. 写一个装饰器,限制函数调用频率

记录每次调用的时间戳,放进列表。每次调用前检查过去n秒内的调用次数。

def rate_limiter(max_calls, period): 

   def decorator(func):

       calls = []

       @wraps(func)

       def wrapper(args, kwargs):

           now = time.time()

            calls[:] = [t for t in calls if now - t < period] 

           if len(calls) >= max_calls:

               raise Exception('超频了')

           calls.append(now)

           return func(args, kwargs)

       return wrapper

   return decorator

7. 装饰器如何处理被装饰函数的返回值

不少人忘记返回结果。wrapper函数里必须 return func(args, kwargs),不然所有函数都变成返回None。面试时直接写这一行,面试官就知道你懂。

8. 用装饰器实现单例模式

把类的实例存在闭包里,每次调用类前检查实例是否存在。

def singleton(cls): 

   instances = {}

   @wraps(cls)

   def get_instance(args, kwargs):

       if cls not in instances:

           instances[cls] = cls(args, kwargs)

       return instances[cls]

   return get_instance

@singleton

class Database:

   pass

9. 如何判断一个函数是否被装饰了

检查函数有没有 __wrapped__ 属性。使用 @wraps 后,这个属性会被设置。也可以用 inspect.ismethod 或 type(func).__name__ 判断。面试官喜欢追问这个。

10. 装饰器里出现异常如何处理

有两种做法。一种是在wrapper里加try-except,捕获异常后记录日志再重新抛出。另一种是定义错误处理函数,由使用者决定怎么处理。

def error_handler(func): 

   @wraps(func)

   def wrapper(args, kwargs):

       try:

           return func(args, kwargs)

       except Exception as e:

           print(f'出错啦: {e}')

           raise

   return wrapper

这几个题目刷完,面试官问你装饰器,你就不用慌了。关键是自己动手敲一遍,别光看。

最新文章

随机文章