如何在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
关键逻辑说明
解决字符串参数问题:
- 在
__getattribute__中通过super().__getattribute__(name)获取实际的属性对象,而非字符串; - 在
__setattr__中通过type(self)获取类对象,再用getattr(cls, name)拿到对应的MyObj实例。
- 在
避免手动编写getter/setter:
- 只要
MyClass的类属性是MyObj实例,就会自动触发代理逻辑,无需为每个属性单独编写方法。
- 只要
保持类的易用性:
- 用户读写
item1/item2等属性的语法和普通Python类完全一致,完全感知不到MyObj的存在。
- 用户读写
保护类属性不被替换:
__setattr__中先判断属性是否为类定义的MyObj实例,仅调用其set_value方法,不会替换掉类属性本身。
内容的提问来源于stack exchange,提问作者user9328856
相关产品推荐
相关产品推荐

