【发布时间】:2012-04-14 14:19:27
【问题描述】:
这是一个设计原则问题,适用于处理数学/物理方程的类,其中允许用户设置计算剩余部分的任何参数。 在这个例子中,我希望能够同时设置频率,同时避免循环依赖。
例如:
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
这里我也知道一个更新触发时间问题,因为我不知道触发更新的顺序:
- 正在更改波长
- 这会触发两个相关实体的更新:频率和能量
- 但是能量需要更新频率,以便能量具有适合新波长的值!
(被接受的答案也应该解决这个潜在的时间问题。)
那么,解决这些相互依赖的问题的最佳设计模式是什么? 最后,我希望用户能够更新波长或频率,并且频率/波长和能量应相应更新。
这类问题当然会出现在几乎所有试图处理方程式的课程中。
让比赛开始吧! ;)
【问题讨论】:
-
我认为traits.api 可能对您的需求来说太过分了。是否有任何理由标准问题属性不适合您? Traits 主要用于设置类间的依赖关系,而不是我在他们页面上看到的类内依赖关系;你正在做类内依赖。
-
我不同意,因为类内依赖对于设计 GUI 非常有帮助,相关的 traits.ui 库是建立在特征之上的。
-
即用于解决一些计算/数据分析任务的迷你图形用户界面或迷你应用程序。这些对于大型 GUI 应用程序的效果如何,我不知道,但至少对于 GUI 元素触发内容和其他内容自动更新的快速应用程序开发,这些属性非常巧妙。
-
但是,如果您的值是从一开始就派生出来的,那么标准问题属性就可以正常工作。您有 1 个基本价值,然后是 2 个常数。你让你的属性 getter 都从基本值计算,然后你的 setter 都转换为基本值。使用 traits.api(你甚至还没有)所得到的只是一种基本上缓存结果的方法,无论如何这都是过早的优化。