MST

星途 面试题库

面试题:Python元类下子类初始化方法的特殊考量与实现

定义一个元类`Meta`,用于创建一类特殊的类,这些类在子类初始化时,需要动态地根据类属性生成额外的实例属性,并且在初始化方法中要处理好这些动态生成属性与继承属性之间的关系。请编写完整的元类`Meta`、使用该元类的父类`Base`以及一个继承自`Base`的子类`Sub`,并详细说明在子类初始化过程中各个步骤的执行逻辑以及需要注意的要点。
11.7万 热度难度
编程语言Python

知识考点

AI 面试

面试题答案

一键面试
class Meta(type):
    def __new__(cls, name, bases, attrs):
        new_attrs = {}
        for key, value in attrs.items():
            if not key.startswith('__'):
                def create_getter(key):
                    def getter(self):
                        return getattr(self, f'_{key}')
                    return getter
                def create_setter(key):
                    def setter(self, value):
                        setattr(self, f'_{key}', value)
                    return setter
                new_attrs[f'get_{key}'] = create_getter(key)
                new_attrs[f'set_{key}'] = create_setter(key)
        new_attrs.update(attrs)
        return super().__new__(cls, name, bases, new_attrs)


class Base(metaclass=Meta):
    def __init__(self, **kwargs):
        for key, value in kwargs.items():
            setattr(self, f'_{key}', value)


class Sub(Base):
    class_attr = 'default_value'

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        if hasattr(self.__class__, 'class_attr'):
            setattr(self, '_class_attr', self.__class__.class_attr)


子类初始化过程执行逻辑

  1. 元类Meta__new__方法:
    • 遍历类属性attrs,对于非特殊属性(不以__开头),为每个属性动态生成get_属性名set_属性名方法。
    • 将这些新生成的方法和原有的类属性合并到new_attrs字典中。
    • 使用super().__new__创建新的类对象并返回。
  2. 父类Base__init__方法:
    • 接受kwargs参数,将传入的键值对设置为实例的私有属性(属性名前加_)。
  3. 子类Sub__init__方法:
    • 首先调用super().__init__(**kwargs),执行父类的初始化逻辑,处理传入的kwargs
    • 检查子类是否有class_attr类属性,如果有,则将其设置为实例的私有属性_class_attr

需要注意的要点

  1. 元类中的属性处理:
    • 要注意避免覆盖原有的特殊方法(如__init__等),只处理自定义的普通类属性。
  2. 继承关系处理:
    • 子类初始化时先调用父类的初始化方法,以确保父类的初始化逻辑正常执行,避免破坏继承体系。
  3. 动态属性生成:
    • 在动态生成gettersetter方法时,要注意闭包中变量的作用域问题,确保生成的方法能正确访问和操作对应的实例属性。