MST

星途 面试题库

面试题:Python元编程之高级难度:实现自定义元类控制属性访问

编写一个Python元类,使得通过该元类创建的类,其所有属性在被访问时,先打印一条日志信息,表明属性被访问了,然后再返回属性值。请给出完整的代码实现,并解释代码的工作原理。
30.4万 热度难度
编程语言Python

知识考点

AI 面试

面试题答案

一键面试
class LoggingMeta(type):
    def __new__(mcls, name, bases, attrs):
        def new_getattribute(self, attr):
            print(f"访问属性: {attr}")
            return super().__getattribute__(attr)
        attrs['__getattribute__'] = new_getattribute
        return super().__new__(mcls, name, bases, attrs)


class MyClass(metaclass=LoggingMeta):
    def __init__(self):
        self.value = 42


obj = MyClass()
print(obj.value)

代码工作原理解释

  1. 定义元类 LoggingMeta
    • __new__ 方法是元类中用于创建类对象的方法。它接收元类自身(mcls)、类名(name)、基类元组(bases)和类属性字典(attrs)作为参数。
    • __new__ 方法中,定义了一个新的 __getattribute__ 方法。这个新方法会在每次访问对象的属性时被调用。它首先打印日志信息,表明哪个属性被访问了,然后通过 super().__getattribute__(attr) 调用原始的 __getattribute__ 方法来获取属性值。
    • 将新的 __getattribute__ 方法添加到类属性字典 attrs 中。
    • 最后,通过调用 super().__new__(mcls, name, bases, attrs) 创建并返回新的类对象。
  2. 定义使用元类的类 MyClass
    • MyClass 使用 LoggingMeta 作为元类,通过 metaclass=LoggingMeta 声明。
    • MyClass 有一个简单的构造函数 __init__,初始化了一个属性 value
  3. 创建对象并访问属性
    • 创建 MyClass 的实例 obj
    • 当访问 obj.value 时,由于 MyClass 是由 LoggingMeta 元类创建的,会调用新定义的 __getattribute__ 方法,先打印日志,然后返回属性值。