【问题标题】:Can you set a dictionary value dependant on another dictionary entry?您可以设置依赖于另一个字典条目的字典值吗?
【发布时间】:2014-04-23 11:40:53
【问题描述】:

我的想法是这样的:

dict1 = {key1:3, key2:5, key3:key1+key2}
# so key3 relate to the value: 8 (3+5)
dict1.update({key2:6})
# key3 will now relate to the value: 9 (3+6)

我试图避免更新不必要的条目,并基于在比较关系值时已经在一系列查找和更新中计算的值构建新的键值关系。字典的哈希性对于让我在查找时或多或少保持恒定时间至关重要。

【问题讨论】:

  • 您的意思是,您想动态更新key3 的值?你的意思是dict1[key1] + dict1[key2],不是吗?
  • 没有这样的方式。对于一般情况,您需要构建一个依赖图并使用 lambdas 或带有 dict 子类的东西来在另一个值更改时重新计算所有依赖值。这就像电子表格软件所做的那样。
  • 还可以查看 dict viewobjects。我看不出如何将它们应用于您的要求,但也许您会找到一种方法:docs.python.org/2.7/library/…
  • 如果你愿意,你可以构建所有这些机器,但你需要的不仅仅是一个普通的字典,而且语法可能会变得很麻烦。

标签: python dictionary dependencies key-value


【解决方案1】:

这不是通用解决方案,但大致适用于您的示例:

class DynamicDict(dict):
    def __getitem__(self, key):
        value = super(DynamicDict, self).__getitem__(key)
        return eval(value, self) if isinstance(value, str) else value

>>> d = DynamicDict(key1=3, key2=5, key3='key1+key2')
>>> d.update({'key2': 6})
>>> d['key3']
9

【讨论】:

  • 我很惊讶eval 实际上调用了真正的__getitem__ 方法,而不是使用内部调用。只要表达式相对简单,就可以很好地工作。如果表达式变得更复杂,或者如果依赖图变得不平凡,这可能会导致大量的重新计算。值得注意的是,eval 在您传递的 globals dict 中添加了一个 __builtins__ 条目,这可能会混淆不期望的代码。
  • 在更复杂的用例中,您可以通过记忆化来增强它,也许利用 __missing__ 方法来加速已经计算值的情况,并在以下情况下使缓存的依赖值无效他们依赖于变化的条目。我可以很好地看到这种概括......但只要它只需要按照问题包含的顺序处理输入复杂性,就不值得所有额外的代码和错误。
【解决方案2】:

您可以通过创建dict 的子类并覆盖__getitem__ 方法来做到这一点:

class My_dict(dict):
    def __getitem__(self, key):
        if key == 'key3':
            return self['key1'] + self['key2']
        return dict.__getitem__(self, key)

dict1 = My_dict(key1=3, key2=5)
print dict1['key3']               #prints 8
dict1.update({'key2':6})         
print dict1['key3']               #prints 9

【讨论】:

  • 我同意,恕我直言。
  • 适用于这种特定情况,但如果您需要更改公式或哪些键取决于其他哪些键,则不能很好地概括。不过,构建通用解决方案并不简单。
  • 这并不绝对有效 - 必须在“getitem”函数中对每个公式进行硬编码 - 检查 Mathew 的答案,了解通用的几行方式,具体取决于 eval。那行得通。
  • @jsbueno 如果我想在该解决方案中定义一个像key4='A' 这样的键,然后尝试访问它,它将无法工作。 IMO 最好明确定义条件而不是使用 eval
  • 如果您没有看到,该解决方案是 3 行函数 - 当然,这件事必须经过深思熟虑才能允许访问非公式值,并检索原始表达式,如果需要的话。这并没有改变这个答案中定义的提案是一个尴尬的反模式这一事实,尽管它可能很糟糕。
猜你喜欢
  • 2020-01-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多