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

Python实现MainClass感知其持有的SubClass实例属性变更的方法

解决方案

核心思路是采用观察者模式,让子属性类在自身属性变更时主动通知父类,无需额外的拷贝对比开销,也支持多属性扩展。

方案1:基础回调通知实现

这个方案适配你当前的代码结构,改动最小:
首先给SubClass增加变更回调钩子,属性修改时触发回调通知父类:

class SubClass:
    def __init__(self, on_change=None):
        self._param = None
        # 存储变更回调函数,触发时会传入[变更属性名, 新值]
        self.on_change = on_change

    @property
    def param(self):
        return self._param

    @param.setter
    def param(self, value):
        print('set param')
        self._param = value
        # 属性变更后触发回调
        if self.on_change:
            self.on_change("param", value)

然后MainClass在初始化子实例时传入回调方法,接收变更通知:

class MainClass:
    def __init__(self):
        # 初始化子实例时传入自身的通知处理方法
        self._var = SubClass(on_change=self._on_var_prop_change)

    @property
    def var(self):
        print('read var')
        return self._var

    @var.setter
    def var(self, value):
        print('set var')
        self._var = value
        # 如果是替换整个子实例,要给新实例重新绑定回调
        self._var.on_change = self._on_var_prop_change

    # 子属性变更的处理逻辑,在这里可以感知到所有子属性的修改
    def _on_var_prop_change(self, prop_name, new_value):
        print(f"MainClass感知到var的属性{prop_name}被修改为{new_value}")

测试运行你给出的用例:

cls = MainClass()
cls.var.param = 3

输出结果:

read var
set param
MainClass感知到var的属性param被修改为3

扩展适配场景

1. 多子属性/多子实例的情况

如果MainClass有多个类似var的子属性,只需要给不同子实例绑定不同的回调,或者在回调中增加实例标识即可:

# 回调可以增加实例标识参数
def _on_sub_prop_change(self, sub_instance_name, prop_name, new_value):
    print(f"MainClass感知到{sub_instance_name}的属性{prop_name}被修改为{new_value}")

# 初始化不同子实例时传入不同标识
self._var1 = SubClass(on_change=lambda name, val: self._on_sub_prop_change("var1", name, val))
self._var2 = SubClass(on_change=lambda name, val: self._on_sub_prop_change("var2", name, val))

2. 数组类型属性修改元素的感知

如果param是数组,直接修改数组元素(如cls.var.param[0] = 5)不会触发property的setter,此时可以自定义可观察数组类:

class ObservableList(list):
    def __init__(self, *args, on_change=None, **kwargs):
        super().__init__(*args, **kwargs)
        self.on_change = on_change

    def __setitem__(self, key, value):
        super().__setitem__(key, value)
        if self.on_change:
            self.on_change(f"索引{key}修改", value)

    def append(self, value):
        super().append(value)
        if self.on_change:
            self.on_change("追加元素", value)

    # 其他需要监听的修改方法比如pop、insert、extend等按同样逻辑重写即可

在SubClass的param setter中给数组绑定回调即可:

@param.setter
def param(self, value):
    print('set param')
    # 如果赋值的是普通列表,自动转为可观察列表
    if isinstance(value, list) and not isinstance(value, ObservableList):
        value = ObservableList(value, on_change=lambda act, val: self.on_change(f"param.{act}", val))
    self._param = value
    if self.on_change:
        self.on_change("param", value)

通用优化方案

如果子属性类有大量属性需要监听,可以通过元类或者描述符统一注入通知逻辑,无需每个属性的setter都手写回调触发代码,进一步降低重复代码量。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 04:36:10