如何让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类的xproperty,所以如果多个Normalised实例绑定不同的Raw实例,后面的绑定会覆盖前面的setter逻辑,导致之前的Normalised实例无法自动触发。 - 适合一对一绑定的场景,或者你能确保每个
Raw类只会被一个Normalised实例绑定。
备注:内容来源于stack exchange,提问作者THATS MY QUANT MY QUANTITATIVE
相关产品推荐
相关产品推荐

