You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过元类为类实例的非魔法属性添加custom_前缀?

用元类自动为实例属性添加前缀的解决方案

要解决实例初始化时self.val无法自动转为self.custom_val的问题,我们可以通过元类在创建类时自动注入自定义的__setattr__方法,拦截所有实例属性的赋值操作,为非魔法属性自动添加前缀。无需手动在类中编写__setattr__,完全通过元类实现逻辑注入。

完整代码实现

class CustomMeta(type):
    def __new__(cls, name, bases, attrs):
        # 处理类属性与方法:为非魔法成员添加custom_前缀
        processed_attrs = {}
        for attr_name, attr_value in attrs.items():
            if not (attr_name.startswith('__') and attr_name.endswith('__')):
                processed_attr_name = f"custom_{attr_name}"
                processed_attrs[processed_attr_name] = attr_value
            else:
                processed_attrs[attr_name] = attr_value

        # 定义自定义__setattr__:拦截实例属性赋值,自动加前缀
        def custom_setattr(self, attr_name, value):
            # 跳过魔法属性(如__dict__、__class__等)
            if not (attr_name.startswith('__') and attr_name.endswith('__')):
                attr_name = f"custom_{attr_name}"
            # 调用最底层的object.__setattr__完成赋值,避免递归
            object.__setattr__(self, attr_name, value)

        # 将自定义__setattr__注入到类中
        processed_attrs['__setattr__'] = custom_setattr

        # 创建并返回处理后的类
        return super().__new__(cls, name, bases, processed_attrs)

# 测试用类
class CustomClass(metaclass=CustomMeta):
    x = 5
    y = 8

    def __init__(self, val):
        self.val = val

    def line(self):
        return 100

    def __str__(self):
        return "CustomClass"

# 验证功能
inst = CustomClass(99)
assert inst.custom_val == 99  # 初始化的self.val自动转为self.custom_val
assert inst.custom_x == 5     # 类属性x已转为custom_x
assert inst.custom_line() == 100  # 类方法line已转为custom_line
print("所有断言通过")

关键逻辑说明

  1. 元类处理类成员:在__new__方法中遍历类的所有属性和方法,为非魔法成员(不以__开头和结尾的名称)添加custom_前缀,这部分是你已实现的逻辑。
  2. 注入自定义__setattr__:
    • 这个方法会拦截所有实例属性的赋值操作,判断属性名是否为魔法属性,若非魔法属性则自动添加前缀。
    • 调用object.__setattr__而非super().__setattr__,是为了避免触发父类可能存在的自定义__setattr__,确保赋值操作直接作用于实例的属性字典。
  3. 自动生效:元类创建CustomClass时,会自动将自定义__setattr__绑定到类上,因此所有CustomClass的实例在赋值属性时都会自动应用前缀逻辑。

可选扩展:支持属性反向访问

如果需要让用户通过inst.val也能访问到inst.custom_val的值,可以在元类中额外注入__getattr__方法:

def custom_getattr(self, attr_name):
    if not (attr_name.startswith('__') and attr_name.endswith('__')):
        try:
            return object.__getattribute__(self, f"custom_{attr_name}")
        except AttributeError:
            raise AttributeError(f"'{type(self).__name__}' object has no attribute '{attr_name}'")
    raise AttributeError(f"'{type(self).__name__}' object has no attribute '{attr_name}'")

# 在processed_attrs中添加__getattr__
processed_attrs['__getattr__'] = custom_getattr

这样用户访问inst.val时,会自动映射到inst.custom_val,进一步提升使用便利性。

内容的提问来源于stack exchange,提问作者jadrezz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 05:33:30