MST

星途 面试题库

面试题:Python元编程中类装饰器的复杂逻辑实现

设计一个Python类装饰器,它能够将被装饰类的所有公开方法(非私有方法)动态地添加一个日志记录功能,记录方法的调用时间、传入参数和返回值。要求在装饰器中使用元类来实现更灵活的定制。
30.8万 热度难度
编程语言Python

知识考点

AI 面试

面试题答案

一键面试
import functools
import time


class LoggerMeta(type):
    def __new__(mcs, name, bases, attrs):
        for attr_name, attr_value in attrs.items():
            if not attr_name.startswith('__') and callable(attr_value):
                @functools.wraps(attr_value)
                def wrapper(*args, **kwargs):
                    start_time = time.time()
                    result = attr_value(*args, **kwargs)
                    end_time = time.time()
                    print(f"Method {attr_name} called at {time.ctime(start_time)}, "
                          f"args: {args}, kwargs: {kwargs}, return value: {result}, "
                          f"execution time: {end_time - start_time} seconds")
                    return result
                attrs[attr_name] = wrapper
        return super().__new__(mcs, name, bases, attrs)


def log_methods(cls):
    return LoggerMeta(cls.__name__, cls.__bases__, dict(cls.__dict__))


@log_methods
class MyClass:
    def add(self, a, b):
        return a + b


if __name__ == "__main__":
    my_obj = MyClass()
    result = my_obj.add(2, 3)

解释:

  1. LoggerMeta元类
    • __new__方法是元类创建类对象时调用的方法。
    • 遍历类的属性,对于非私有且可调用的属性(即公开方法),使用functools.wraps装饰器创建一个包装函数wrapper
    • wrapper函数记录方法调用时间、传入参数、返回值和执行时间,并打印日志。
  2. log_methods装饰器
    • 使用LoggerMeta元类来创建一个新的类对象,这个新类对象的公开方法都被添加了日志记录功能。
  3. MyClass类
    • 使用@log_methods装饰器装饰,其公开方法add在调用时会记录日志。