2015-04-23 2 views
3

J'essaye de tracer une structure de données pour effectuer l'opération suivante.Utiliser un dict comme clé composite d'un autre dict python (paire clé-valeur)

Je veux une paire clé-valeur qui ressemble à ceci. Ce que je veux, c'est renvoyer un objet dict de style json quand la couleur est rouge, la forme est un cercle. Renvoyer un autre objet dict de style json lorsque la couleur est bleue, la forme est carrée, etc.

Donc, ma clé n'est pas vraiment une clé normale. C'est une sorte de clé composite. Veuillez suggérer

+0

JSON permet uniquement les clés de chaîne dans les dicts. – warvariuc

+0

Et la seule façon de procéder serait de créer votre propre classe qui hériterait du type de dict interne et d'implémenter votre propre fonction '__hash__', mais cela entraînerait à mon tour une présomption de chaîne. le dict et si l'objet clé est un dict le convertir en un objet chaîne. Vous pourriez alors potentiellement boucler dessus en JavaScript et convertir la clé (chaîne) en dict en la chargeant dans le décodeur sur une autre boucle. Conversion en deux étapes ou simplement implémenter '__hash__' dans une classe-dict définie par l'utilisateur. – Torxed

Répondre

1

JSON ne supporte pas ce que vous cherchez, pas plus que Python puisque les objets dict ne sont pas traitables. Je vais pour un namedtuple dans ce cas, puisque vous (je l'espère) connaître à l'avance ce que commettants votre clé aura:

from collections import namedtuple 
MyKey = namedtuple("MyKey", "color shape".split()) 

my_dict = { 
    MyKey(color="red", shape="circle"): {...} 
} 
0

Vous ne pouvez pas utiliser un objet dict comme la clé en python. Ce que je ferais est d'utiliser quelque chose immutable comme clé: au lieu de l'objet dict lui-même j'utilise sa représentation de chaîne.

2

Cela ne peut pas être fait en Python. Vous recevrez un TypeError. La raison en est qu'une clé de dictionnaire doit être être un objet pouvant être pris en charge, ce qui n'est pas le cas d'un . À titre d'exemple, essayez ceci:

>>> 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' 
>>> 

La raison pour laquelle dict s ne sont pas indexables est qu'ils sont mutables objets. Cela signifie (grosso modo) qu'ils peuvent changer (bien que ce soit un peu plus subtil que cela, pour citer les docs Python). IIRC, sous le capot, Python utilise des tables de hachage pour implémenter les clés du dictionnaire, donc si un objet n'est pas lavable, il ne peut pas être utilisé comme une clé. Consultez la section Data Model des documentations Python pour plus d'informations sur les objets mutables et immuables.

Comme d'autres l'ont dit, vous devez utiliser un objet immuable, comme un tuple ou un namedtuple, pour votre clé:

>>> 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': [{}, {}, {}, {}]} 
>>>