Использование словаря Python в качестве ключа (не вложенный)
-
05-07-2019 - |
Вопрос
Python не позволяет использовать словари в качестве ключей в других словарях. Есть ли обходной путь для использования не вложенных словарей в качестве ключей? Р>
Общая проблема с более сложными объектами без хэширования и моим конкретным примером использования была переехал сюда . Мое первоначальное описание моего варианта использования было неверным.
Решение
Если у вас есть действительно неизменный словарь (хотя мне непонятно, почему вы не просто используете список пар: например, [('content-type', 'text / plain'), ('host', 'example.com')]
), тогда вы можете преобразовать свой dict
в:
Кортеж пар. Вы уже сделали это в своем вопросе. tuple
требуется вместо list
, потому что результаты зависят от упорядоченности и неизменности элементов.
>>> tuple(sorted(a.items()))
Замороженный набор. Это более подходящий подход с математической точки зрения, поскольку он требует только отношения равенства для элементов вашего неизменяемого dict
, тогда как первый подход требует отношения порядка кроме равенства.
>>> frozenset(a.items())
Другие советы
Если бы мне нужно было использовать словари в качестве ключей, я бы выровнял словарь в кортеж кортежей.
Этот вопрос может оказаться полезным: Как лучше всего реализовать вложенные словари?
А вот пример модуля сглаживания, который сгладит словари: http://yawpycrypto.sourceforge.net/html/public/Flatten.Flatten-module.html р>
Я не совсем понимаю ваш вариант использования и подозреваю, что вы пытаетесь преждевременно оптимизировать то, что не требует оптимизации. Р>
Один из способов сделать это - создать подкласс dict и предоставить метод хеширования. то есть:
class HashableDict(dict):
def __hash__(self):
return hash(tuple(sorted(self.iteritems())))
>>> d = HashableDict(a=1, b=2)
>>> d2 = { d : "foo"}
>>> d2[HashableDict(a=1, b=2)]
"foo"
Однако имейте в виду причины, по которым dicts (или любые изменяемые типы) этого не делают: изменение объекта после его добавления в хеш-таблицу изменит хеш, что означает, что dict теперь будет иметь его в неправильное ведро, и поэтому будут возвращены неверные результаты.
Если вы идете по этому пути, либо очень убедитесь, что дикты никогда не изменятся после того, как они были помещены в другой словарь, либо активно их предотвращайте (например, проверьте, что хеш никогда не меняется после сначала вызовите __ hash __
и, если нет, создайте исключение.)
Хм, разве ваш случай использования не запоминает вызовы функций? Используя декоратор, вы будете легко поддерживать произвольные функции. И да, они часто перебирают аргументы, и, используя циклические рассуждения, это работает для нестандартных типов, если их можно перебрать.
Смотрите, например, этот образец заметок
Чтобы превратить someDictionary в ключ, сделайте это
key = tuple(sorted(someDictionary .items())
Вы можете легко изменить это с помощью dict (key)
Я не понимаю, почему вы захотите это сделать, но если вам действительно это нужно, вы можете попробовать выбрать словарь:
mydict = {"a":1, "b":{"c":10}}
import pickle
key = pickle.dumps(mydict)
d[key] = value
эта функция преобразует вложенный словарь в неизменный набор кортежей, который вы можете использовать в качестве ключа:
def convert_dictionary_tuple(input_dict):
"""
this function receives a nested dictionary and convert it to an immutable tuple of tuples with all the given
dictionary data
:param input_dict: a nested dictionary
:return: immutable tuple of tuples with all the given dictionary data
"""
tuples_dict = {}
for key, value in input_dict.iteritems():
if isinstance(value, dict):
tuples_dict[key] = convert_dictionary_tuple(value)
elif isinstance(value, list):
tuples_dict[key] = tuple([convert_dictionary_tuple(v) if isinstance(v, dict) else v for v in value])
else:
tuples_dict[key] = value
return tuple(sorted(tuples_dict.items()))
Я не знаю, правильно ли я понимаю ваш вопрос, но я попробую
d[repr(a)]=value
Вы можете использовать словарь следующим образом:
for el1 in d:
for el2 in eval(el1):
print el2,eval(el1)[el2]