Use dict as composite key of another python python (key-value pair)
I am trying to create a data structure to perform the following operation.
I want a key-value pair to look something like this.
{
{"color": "red", "shape": "circle"}: {data: [{}, {}, {}, {}]}
, {"color": "blue", "shape": "square"}: {data: [{}, {}, {}, {}]}
, {"color": "blue", "shape": "circle"}: {data: [{}, {}, {}, {}]}
, {"color": "red", "shape": "square"}: {data: [{}, {}, {}, {}]}
}
What I want is to return a json style object when the color is red the shape is circle. Return another json style object when color is blue, shape is square, etc.
So my key is not a regular key. It's kind of a tricky key. Please suggest
source to share
This cannot be done in Python. You will receive TypeError
. The reason for this is that the dictionary key must be a hashable object, dict
not. Try this as an example:
>>> 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'
>>>
The reason dict
not hashing is because they are mutable objects. This means (roughly) that they can change (although this is a little more subtle than that, to quote the Python docs). IIRC, under the hood, Python uses hash tables to implement dictionary keys, so if an object is not hashable it cannot be used as a key. See the Data Model section in the Python docs for more information on mutable and immutable objects.
As others have said, you should use an immutable object like a tuple or namedtuple for your key:
>>> 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': [{}, {}, {}, {}]}
>>>
source to share
JSON does not support what you are looking for and Python as objects are dict
not hashed. I would go for it namedtuple
in this case, since you (hopefully) know what constituents you will have your key:
from collections import namedtuple
MyKey = namedtuple("MyKey", "color shape".split())
my_dict = {
MyKey(color="red", shape="circle"): {...}
}
source to share