构建变量依赖项

时间:2015-03-27 21:16:58

标签: python python-3.x dependencies

我正在尝试在Python中构建一些变量依赖项。例如,如果a = xb = yc = a + b,则如果ab发生更改,c的值应自动更新。我知道Python变量和值在标签的基础上工作,并且一直在尝试使用__setattr__来解决这个问题。由于__setattr__中的循环依赖,我似乎在执行此操作时遇到了一些麻烦。

考虑这个小代码片段:

class DelayComponents(object):
    '''
    Delay Components Class
    '''

    def __init__(self, **delays):
        '''
        Constructor
        '''
        self.prop_delay = round(float(delays['prop_delay']), 2)
        self.trans_delay = round(float(delays['trans_delay']), 2)
        self.proc_delay = round(float(delays['proc_delay']), 2)
        self.queue_delay = round(float(delays['queue_delay']), 2)
        self.delay = (self.prop_delay + self.proc_delay +
                      self.trans_delay + self.queue_delay)

    def __setattr__(self, key, value):
        self.__dict__[key] = value
        if (key in ("prop_delay", "trans_delay",
                    "proc_delay", "queue_delay")):
            self.delay = (self.prop_delay + self.proc_delay +
                      self.trans_delay + self.queue_delay)

这似乎很好地达到了目的,但是当我第一次创建DelayComponents的对象时,由于__setattr__被覆盖并且为每个创建的值调用,{在if内检查{1}}会抛出错误,说明还没有找到剩下的三个变量(这是真的,因为它们尚未创建)。

如何解决此依赖关系?

另外,有没有办法用__setattr__完成同样的事情?更具体地说,如果三个变量实际上是dict中的键值对,其中第三个键的值是前两个键的值的总和,则可以在前两个键中的任何一个时自动更新第三个值变化?

1 个答案:

答案 0 :(得分:1)

假设您希望取消设置_delay__init____setattr__)的默认值为零,则可以执行以下操作:

class DelayComponents(object):
    '''
    Delay Components Class
    '''

    ATTRS = ['prop_delay', 'trans_delay', 'proc_delay', 'queue_delay']

    def __init__(self, **delays):
        '''
        Constructor
        '''
        for attr in self.ATTRS:
            setattr(self, attr, round(float(delays.get(attr, 0)), 2))
        # No point in setting delay here - it's already done!

    def __setattr__(self, key, value):
        super(DelayComponents, self).__setattr__(key, value)
        # This avoids directly interacting with the __dict__
        if key in self.ATTRS:
            self.delay = sum(getattr(self, attr, 0) for attr in self.ATTRS)

使用中:

>>> d = DelayComponents(prop_delay=1, trans_delay=2, proc_delay=3, queue_delay=4)
>>> d.delay
10.0

如果您想要不同属性的默认值不同,DelayComponents.ATTRS可能是字典{'attribute_name': default_value, ...}


更简单的替代方法是将delay设为@property,仅根据需要计算:

class DelayComponents(object):
    '''
    Delay Components Class
    '''

    ATTRS = ['prop_delay', 'trans_delay', 'proc_delay', 'queue_delay']

    def __init__(self, **delays):
        '''
        Constructor
        '''
        for attr in self.ATTRS:
            setattr(self, attr, round(float(delays.get(attr, 0)), 2))

    @property
    def delay(self):
        return sum(getattr(self, attr, 0) for attr in self.ATTRS)

回答你的子问题:不,没有办法用香草dict做到这一点;密钥的值不会根据计算它们的值的变化进行重新评估。


另外,严肃地说,你当前的文档字符串是没有意义的;你不妨完全抛弃它们。它们不提供任何信息,也不符合PEP-257