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

如何在Python中自定义__setattr__和__getattribute__实现属性代理?

解决方案

首先修正MyObj类的拼写错误(Python中类定义用小写class),然后实现MyClass的属性代理逻辑:

完整代码实现

定义提供读写逻辑的MyObj类

class MyObj:
    def __init__(self):
        self.value = 0

    def set_value(self, value):
        self.value = value

    def get_value(self):
        return self.value

实现属性代理的MyClass类

class MyClass:
    # 定义需要代理的MyObj类属性
    item1 = MyObj()
    item2 = MyObj()
    item3 = MyObj()

    def __getattribute__(self, name):
        # 获取原始属性对象,避免递归调用__getattribute__
        attr_obj = super().__getattribute__(name)
        # 如果是MyObj实例,返回其内部存储的值
        if isinstance(attr_obj, MyObj):
            return attr_obj.get_value()
        # 非MyObj类型的属性正常返回
        return attr_obj

    def __setattr__(self, name, value):
        # 检查当前类是否存在该属性,且属性是MyObj实例
        cls = type(self)
        if hasattr(cls, name) and isinstance(getattr(cls, name), MyObj):
            # 调用MyObj的set_value方法赋值,不替换类属性本身
            getattr(cls, name).set_value(value)
        else:
            # 普通属性正常赋值到实例
            super().__setattr__(name, value)

测试代码

cls = MyClass()
cls.item1 = 10
print(cls.item1)  # 输出: 10

cls.item2 = 20
print(cls.item2)  # 输出: 20

# 支持普通实例属性的正常读写
cls.regular_attr = "hello"
print(cls.regular_attr)  # 输出: hello

关键逻辑说明

  1. 解决字符串参数问题:

    • 在__getattribute__中通过super().__getattribute__(name)获取实际的属性对象,而非字符串;
    • 在__setattr__中通过type(self)获取类对象,再用getattr(cls, name)拿到对应的MyObj实例。
  2. 避免手动编写getter/setter:

    • 只要MyClass的类属性是MyObj实例,就会自动触发代理逻辑,无需为每个属性单独编写方法。
  3. 保持类的易用性:

    • 用户读写item1/item2等属性的语法和普通Python类完全一致,完全感知不到MyObj的存在。
  4. 保护类属性不被替换:

    • __setattr__中先判断属性是否为类定义的MyObj实例,仅调用其set_value方法,不会替换掉类属性本身。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 15:01:19