¿Cuál es la mejor manera de crear claves de tuplas intercambiables para el mismo valor de diccionario?

def check(): dict_choice_a = {(a, b) : value, (b, a) : value} #(a, b) and (b, a) refer to the same value but repeted dict_choice_b = {tuple(sorted((a, b)) : value} #not repetitive but unreadable dict_choice_a[(a, b)] = new_value #need to do twice to change value but more readable than dict_choice_b dict_choice_a[(b, a)] = new_value #value of both keys are always the same 

Quiero crear un dictionary que tenga claves de tupla referidas a sus valores, que las claves deben ser intercambiables como (a, b) = (b, a) y solo se refieren al mismo valor.

La pregunta es: ¿cuál es la mejor manera de hacer que el elemento de tulpe de las teclas sea intercambiable pero también se refiera al mismo valor?

Por otra parte, la cadena también debe ser trabajo en la solución.

Por los comentarios, puede poner a y b en un frozenset , que no está ordenado:

 dict_choice = {frozenset((a, b)): value} 

Si necesita que esto sea automático, puede crear su propio MutableMapping :

 class MyDict(MutableMapping): def __init__(self, arg=None): self._map = {} if arg is not None: self.update(arg) def __getitem__(self, key): return self._map[frozenset(key)] def __setitem__(self, key, value): self._map[frozenset(key)] = value def __delitem__(self, key): del self._map[frozenset(key)] def __iter__(self): return iter(self._map) def __len__(self): return len(self._map) 

En uso:

 >>> d = MyDict([((1, 2), 'hello'), ((3, 4), 'world')]) >>> d[(2, 1)] 'hello' 

Sin embargo, tenga en cuenta que esto podría tener un comportamiento inesperado con otros tipos de claves:

 >>> d['hello'] = 'world' >>> d['hole'] 'world' >>> d[1] = 2 Traceback (most recent call last): File "python", line 1, in  File "python", line 14, in __setitem__ TypeError: 'int' object is not iterable 

Usando la solución @jonrsharpe, creé una alternativa para el comportamiento inesperado con otros tipos de claves, considerando que solo se utilizarán las tuplas de forma desordenada:

 class MyDict(MutableMapping): def __init__(self, arg=None): self._map = {} if arg is not None: self.update(arg) def __getitem__(self, key): if isinstance(key, tuple): return self._map[frozenset(key)] return self._map[key] def __setitem__(self, key, value): if isinstance(key, tuple): self._map[frozenset(key)] = value else: self._map[key] = value def __delitem__(self, key): if isinstance(key, tuple): del self._map[frozenset(key)] else: del self.map[key] def __iter__(self): return iter(self._map) def __len__(self): return len(self._map) def __str__(self): return str(self._map)