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

如何让Normalised类的normalise方法在Raw类实例属性x更新时自动触发(无需显式调用)

如何让Normalised类的normalise方法在Raw类实例属性x更新时自动触发(无需显式调用)

嘿,我完全get到你的需求了——就是希望Normalised的normalise方法能在Raw的x属性更新时自动执行,还不用在Raw里写一堆显式的回调注册或者直接调用的代码,对吧?结合你提出的约束条件(不能用类属性、不能在Raw.update_values里显式调用normalise),我给你准备了两个实用的实现方案,都能满足你的要求。

方案一:隐式回调列表(推荐,支持一对多绑定)

这个方案的核心是在Raw类里悄悄加一个实例级的回调列表,然后在x的setter里自动触发所有回调。Normalised实例初始化时会自动把自己的normalise方法注册进去,全程不需要你手动操作。

import numpy as np
import time

class Raw:
    def __init__(self, x):
        self._x = x
        # 每个Raw实例自己的回调列表,属于实例属性,符合你的约束
        self._x_update_callbacks = []
        
    @property
    def x(self):
        return self._x
    
    @x.setter
    def x(self, new_value):
        self._x = new_value
        # x更新后自动触发所有绑定的回调,不用在update_values里写额外代码
        for callback in self._x_update_callbacks:
            callback()
        
    def update_values(self, counter):
        self.x = self.x + counter + np.random.normal(0,0.3)
        
class Normalised:
    def __init__(self, raw_obj: Raw, name=""):
        self.raw = raw_obj  
        self.name = name
        self.norm = self.normalise()
        # 自动注册回调,用户完全不用手动调用add_callback
        raw_obj._x_update_callbacks.append(self.normalise)
        
    def normalise(self):
        x = self.raw.x  
        self.norm = (x - x.min()) / (x.max() - x.min())
        print(f"{self.name} 已自动归一化: {self.norm}")
        return self.norm

data_1 = Raw(np.arange(10))
data_2 = Raw(20 * np.arange(10))

data_normalised_1 = Normalised(data_1, "object_1")
data_normalised_2 = Normalised(data_2, "object_2")

while True:
    data_1.update_values(1)
    data_2.update_values(2)
    time.sleep(2)

方案优势:

  • 完全符合你的约束:所有属性都是实例属性,Raw.update_values里没有任何显式调用normalise的代码
  • 支持一个Raw实例绑定多个Normalised实例,所有绑定的normalise方法都会自动触发
  • 逻辑清晰,后续维护起来也方便

方案二:动态替换setter(无需修改Raw源码)

如果你不想改动Raw类的原始代码,这个方案可以通过动态替换x的setter,把normalise逻辑绑定进去。

import numpy as np
import time

class Raw:
    def __init__(self, x):
        self._x = x  

    @property
    def x(self):
        return self._x
    
    @x.setter
    def x(self, new_value):
        self._x = new_value
        
    def update_values(self, counter):
        self.x = self.x + counter + np.random.normal(0,0.3)
        
class Normalised:
    def __init__(self, raw_obj: Raw, name=""):
        self.raw = raw_obj  
        self.name = name
        self.norm = self.normalise()
        
        # 获取Raw类的x property对象
        raw_x_property = type(raw_obj).x
        # 保存原始的setter方法
        original_setter = raw_x_property.fset
        
        # 定义包装后的setter:先执行原始逻辑,再触发normalise
        def wrapped_setter(instance, new_value):
            original_setter(instance, new_value)
            self.normalise()
        
        # 替换Raw类的x property的setter
        type(raw_obj).x = property(raw_x_property.fget, wrapped_setter)
        
    def normalise(self):
        x = self.raw.x  
        self.norm = (x - x.min()) / (x.max() - x.min())
        print(f"{self.name} 已自动归一化: {self.norm}")
        return self.norm

data_1 = Raw(np.arange(10))
data_normalised_1 = Normalised(data_1, "object_1")

data_2 = Raw(20 * np.arange(10))
data_normalised_2 = Normalised(data_2, "object_2")

while True:
    data_1.update_values(1)
    data_2.update_values(2)
    time.sleep(2)

注意事项:

  • 这个方法是修改Raw类的x property,所以如果多个Normalised实例绑定不同的Raw实例,后面的绑定会覆盖前面的setter逻辑,导致之前的Normalised实例无法自动触发。
  • 适合一对一绑定的场景,或者你能确保每个Raw类只会被一个Normalised实例绑定。

备注:内容来源于stack exchange,提问作者THATS MY QUANT MY QUANTITATIVE

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.14 11:59:50