设置Properties时如何避免循环依赖?

2023-12-03

这是处理数学/物理方程的类的设计原理问题,其中允许用户设置任何参数,并根据该参数计算其余参数。 在此示例中,我希望能够设置频率,同时避免循环依赖。

例如:

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

我还意识到这里存在更新触发计时问题,因为我不知道触发更新的顺序:

  1. 波长正在改变
  2. 这会触发两个依赖实体的更新:频率和能量
  3. 但是能量需要更新频率,以便能量具有适合新波长的值!

(要接受的答案还应该解决这个潜在的时间问题。)

那么,解决这些相互依赖的问题的最佳设计模式是什么? 最后,我希望用户能够更新波长或频率,并且频率/波长和能量应相应更新。

当然,基本上所有尝试处理方程的课程都会出现这种问题。

让比赛开始吧! ;)


感谢来自 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(使用前将#替换为@)

设置Properties时如何避免循环依赖? 的相关文章

随机推荐