【问题标题】:Use a dict as the composite key of another python dict (key-value pair)使用一个dict作为另一个python dict(键值对)的复合键
【发布时间】:2015-04-23 10:27:15
【问题描述】:

我正在尝试构建一个数据结构来执行以下操作。

我想要一个看起来像这样的键值对。

{
  {"color": "red", "shape": "circle"}: {data: [{}, {}, {}, {}]}
, {"color": "blue", "shape": "square"}: {data: [{}, {}, {}, {}]}
, {"color": "blue", "shape": "circle"}: {data: [{}, {}, {}, {}]}
, {"color": "red", "shape": "square"}: {data: [{}, {}, {}, {}]}
}

我想要的是在颜色为红色、形状为圆形时返回一个 json 样式的 dict 对象。当颜色为蓝色、形状为方形等时,返回不同的 json 样式的 dict 对象。

所以,我的钥匙并不是真正的普通钥匙。它是一种复合键。请推荐

【问题讨论】:

  • JSON 只允许字典中的字符串键。
  • 唯一可行的方法是,如果您创建自己的继承内置 dict 类型的类并实现自己的 __hash__ 函数,但这反过来会导致我认为无论如何,字符串,所以只需遍历字典,如果关键对象是字典,则将其转换为字符串对象。然后,您可能会在说 JavaScript 中循环它,并通过在另一个循环中将其加载到解码器中来将键(字符串)转换为 dict。两步转换或仅在用户定义的类字典中实现__hash__

标签: python json dictionary


【解决方案1】:

这不能在 Python 中完成。您将收到TypeError。这样做的原因是字典键 必须 是一个可散列的对象,而 dict 不是。例如,试试这个:

>>> d0 = {'foo': 'bar',}
>>> assert d0 == {'foo': 'bar'}
>>> d1 = {d0: 'baz',}
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'dict'
>>> hash(d0)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'dict'
>>>

dicts 不可散列的原因是它们是可变 对象。这意味着(大致)它们可以改变(尽管引用 Python 文档来说比这更微妙一些)。 IIRC,在底层,Python 使用哈希表来实现字典键,所以如果一个对象不是可散列的,它就不能用作键。有关可变和不可变对象的更多信息,请参阅 Python 文档的 Data Model 部分。

正如其他人所说,您应该使用不可变对象,例如元组或 namedtuple,作为您的密钥:

>>> from collections import namedtuple
>>> colors = 'red blue'.split(' ')
>>> shapes = 'circle square'.split(' ')
>>> Figure = namedtuple('Figure', ('color', 'shape'))
>>> my_dict = {Figure(color, shape): {'data': [{}, {}, {}, {},]}
...            for color in colors for shape in shapes}
>>> assert my_dict == {Figure(color='blue', shape='circle'): {'data': [{}, {}, {}, {}]}, Figure(color='blue', shape='square'): {'data': [{}, {}, {}, {}]}, Figure(color='red', shape='circle'): {'data': [{}, {}, {}, {}]}, Figure(color='red',shape='square'): {'data': [{}, {}, {}, {}]}}
>>> assert my_dict[('blue', 'circle')] == {'data': [{}, {}, {}, {}]}
>>>

【讨论】:

    【解决方案2】:

    JSON 不支持您要查找的内容,Python 也不支持,因为 dict 对象不可散列。在这种情况下,我会选择namedtuple,因为您将(希望)预先知道您的密钥将包含哪些成分:

    from collections import namedtuple
    MyKey = namedtuple("MyKey", "color shape".split())
    
    my_dict = {
       MyKey(color="red", shape="circle"): {...}
    }
    

    【讨论】:

      【解决方案3】:

      您不能在 python 中使用 dict 对象作为键。我要做的是使用一些 immutable 作为键:而不是 dict 对象本身,我使用它的字符串表示。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-05-30
        • 2011-05-30
        • 2016-07-13
        • 1970-01-01
        相关资源
        最近更新 更多