构建变量依赖
Building variable dependencies
我正在尝试在 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__
已被覆盖并为每个正在创建的值调用, __setattr__
中的 if
检查会抛出一个错误,指出还没有找到剩余的三个变量(这是真的,因为它们还没有被创建)。
如何解决这种依赖关系?
另外,有什么方法可以用 dict
完成同样的事情吗?更具体地说,如果这三个变量实际上是 dict 中的键值对,其中第三个键的值是前两个键值的总和,是否有可能在前两个键中的任何一个时自动更新第三个值变化?
假设您希望未设置的 _delay
s(在 __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。
我正在尝试在 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__
已被覆盖并为每个正在创建的值调用, __setattr__
中的 if
检查会抛出一个错误,指出还没有找到剩余的三个变量(这是真的,因为它们还没有被创建)。
如何解决这种依赖关系?
另外,有什么方法可以用 dict
完成同样的事情吗?更具体地说,如果这三个变量实际上是 dict 中的键值对,其中第三个键的值是前两个键值的总和,是否有可能在前两个键中的任何一个时自动更新第三个值变化?
假设您希望未设置的 _delay
s(在 __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。