这是处理数学/物理方程的类的设计原理问题,其中允许用户设置任何参数,并根据该参数计算其余参数。
在此示例中,我希望能够设置频率,同时避免循环依赖。
例如:
from traits.api import HasTraits, Float, Property
from scipy.constants import c, h
class Photon(HasTraits):
wavelength = Float # would like to do Property, but that would be circular?
frequency = Property(depends_on = 'wavelength')
energy = Property(depends_on = ['wavelength, frequency'])
def _get_frequency(self):
return c/self.wavelength
def _get_energy(self):
return h*self.frequency
我还意识到这里存在更新触发计时问题,因为我不知道触发更新的顺序:
- 波长正在改变
- 这会触发两个依赖实体的更新:频率和能量
- 但是能量需要更新频率,以便能量具有适合新波长的值!
(要接受的答案还应该解决这个潜在的时间问题。)
那么,解决这些相互依赖的问题的最佳设计模式是什么?
最后,我希望用户能够更新波长或频率,并且频率/波长和能量应相应更新。
当然,基本上所有尝试处理方程的课程都会出现这种问题。
让比赛开始吧! ;)
感谢来自 Enthought 邮件列表的 Adam Hughes 和 Warren Weckesser,我意识到我的理解中缺少了什么。
属性实际上并不作为属性存在。我现在将它们视为“虚拟”属性,完全取决于类的编写者在调用 _getter 或 _setter 时所做的操作。
因此,当我希望能够由用户设置波长和频率时,我只需要了解频率本身并不作为属性存在,而是在频率的_设置时间我需要更新“基本”属性波长,这样下次需要频率时,就用新的波长重新计算!
我还需要感谢用户sr2222,他让我思考了缓存缺失的问题。我意识到只有在使用“cached_property”特征时才需要使用关键字“depends_on”设置的依赖项。如果计算成本不是那么高或者不经常执行,则 _getters 和 _setter 会处理所需的一切,并且不需要使用“depends_on”关键字。
现在我正在寻找简化的解决方案,它允许我设置波长或频率而无需循环:
class Photon(HasTraits):
wavelength = Float
frequency = Property
energy = Property
def _wavelength_default(self):
return 1.0
def _get_frequency(self):
return c/self.wavelength
def _set_frequency(self, freq):
self.wavelength = c/freq
def _get_energy(self):
return h*self.frequency
人们会这样使用这个类:
photon = Photon(wavelength = 1064)
or
photon = Photon(frequency = 300e6)
要设置初始值并立即获取能量,只需直接使用它:
print(photon.energy)
请注意,_wavelength_default 方法会处理用户在不提供初始值的情况下初始化 Photon 实例的情况。仅对于波长的第一次访问,才会使用该方法来确定它。如果我不这样做,第一次访问频率将导致 1/0 计算。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)