我正在尝试在Python中构建一些变量依赖项。例如,如果a = x
,b = y
和c = a + b
,则如果a
或b
发生更改,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中的键值对,其中第三个键的值是前两个键的值的总和,则可以在前两个键中的任何一个时自动更新第三个值变化?
答案 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。