【发布时间】:2020-03-28 14:11:39
【问题描述】:
如果标题含糊不清,我深表歉意,我想不出用一句话来描述我的问题。我正在 python2.7 中构建一些代码,如下所述。
最小的工作示例
我的代码有一个Parameter 类,它实现了name 和value 等属性,看起来像这样。
class Parameter(object):
def __init__(self, name, value=None, error=None, dist=None, prior=None):
self.name = name
self._value = value # given value for parameter, this is going to be changed very often in an MCMC sampler
self.error = error # initial estimate of error for the parameter, will only be set once
self._dist = dist # a distribution for the parameter, will only be set once
self.prior = prior
@property
def value(self):
return self._value
@property
def dist(self):
return self._dist
如果给定分布,该类还有几个属性可以返回Parameter.dist 的平均值、中位数等。
我还有一门课,例如ParameterSample,它创建了一组不同的 Parameter 对象。其中一些Parameter 对象的属性(例如value、error)使用Parameter.set_parameter() 函数设置,但其他一些Parameter 对象没有显式设置,但它们的value 和dist 属性依赖设置的其他一些Parameter对象:
class ParameterSample(object):
def __init__(self):
varied_parameters = ('a', 'b') # parameter names whose `value` attribute is varied
derived_parameters = ('c',) # parameter names whose `value` attribute is varied, but depends on `a.value` and `b.value`
parameter_names = varied_parameters + derived_parameters
# create `Parameter` objects for each parameter name
for name in parameter_names:
setattr(self, name, Parameter(name))
def set_parameter(self, name, **kwargs):
for key, val in kwargs.items():
if key == 'value':
key = '_'.join(['', key]) # add underscore to set `Parameter._value`
setattr(getattr(self, name), key, val) # basically does e.g. `self.a.value = 1`
我现在可以创建一个ParameterSample 并像这样使用它们:
parobj = ParameterSample()
parobj.set_parameter('a', value=1, error=0.1)
parobj.set_parameter('b', value=2, error=0.5)
parobj.a.value
>>> 1
parobj.b.error
>>> 0.5
parobj.set_parameter('b', value=3)
parobj.b.value
>>> 3
parobj.b.error
>>> 0.5
我想要什么
我最终想要的是以同样的方式使用Parameter.c。例如:
parobj.c.value
>>> 4 # returns parobj.a.value + parobj.b.value
parobj.c.dist
>>> None # returns a.dist + b.dist, but since they are not currently set it is None
c 因此需要是一个Parameter 对象,具有与a 和b 相同的属性,但是它的value 和dist 根据a 的当前属性进行更新和b。
但是,我还应该提到,我希望能够为参数 c 设置允许的先验范围,例如parobj.set_parameter('c', prior=(0,10)) 在对其值进行任何调用之前 -- 因此 c 需要在创建 ParameterSample 对象时是已定义的 Parameter 对象。
如何在我的 ParameterSample 类中实现这一点?
我尝试过的
我尝试过制作自己的装饰器,但我不确定这是否可行,因为我不完全了解如何使用它们。
我还考虑将@property 添加到c,每次调用它都会创建一个新的Parameter 对象,但我觉得这不是可行的方法,因为它可能会减慢代码速度。
我还应该注意,上面的ParameterSample 类将在不同的类中继承,所以无论解决方案是什么,它都应该能够在此设置中使用:
class Companion(ParameterSample)
def __init__(self, name):
self.name = name
super(Companion, self).__init__()
comp = Companion(name='Earth')
comp.set_parameter('a', value=1)
comp.set_parameter('b', value=3)
comp.c.value
>>> 4
【问题讨论】:
-
仅作记录。你真的应该尽快切换到 python 3,因为 python 2 将不被支持。
-
@Error-SyntacticalRemorse 同意,但我必须稍后再做,因为我目前没有能力将我的代码移植到 python 3。
-
c怎么知道引用a和b?有什么d? -
如果有
d怎么办?* -
如果我理解你的问题,
c是ParameterSample的一个属性,与a和b相同,所以它的任何属性都可以在ParameterSample中访问如self.a.value等。