Использование словаря Python в качестве ключа (не вложенного)
Python не позволяет использовать словари в качестве ключей в других словарях. Есть ли способ обхода без вложенных словарей в качестве ключей?
Общая проблема с более сложными не-хэшируемыми объектами и моим конкретным вариантом использования была перенесена здесь. Мое первоначальное описание моего варианта использования было неправильным.
Ответы
Ответ 1
Если у вас есть действительно неизменный словарь (хотя мне не понятно, почему вы не просто используете список пар: например, [('content-type', 'text/plain'), ('host', 'example.com')]
), тогда вы можете преобразовать ваш dict
в:
-
Кортеж пар. Вы уже сделали это в своем вопросе. Вместо list
требуется tuple
потому что результаты зависят от упорядоченности и неизменности элементов.
>>> tuple(sorted(a.items()))
-
Замороженный набор. Это более подходящий подход с математической точки зрения, так как она требует только отношение равенства на элементах вашего неизменного dict
, в то время как первый подход требует упорядочения отношений, кроме равенства.
>>> frozenset(a.items())
Ответ 2
Если мне нужно было использовать словари как ключи, я бы сгладил словарь в кортеж кортежей.
Возможно, этот вопрос полезен: Каков наилучший способ реализации вложенных словарей?
И вот пример модуля сглаживания, который будет сглаживать словари: http://yawpycrypto.sourceforge.net/html/public/Flatten.Flatten-module.html
Я не совсем понимаю ваш случай использования, и я подозреваю, что вы пытаетесь преждевременно оптимизировать то, что не нуждается в оптимизации.
Ответ 3
Один из способов сделать это - подклассировать 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 теперь получит его в неправильное ведро, и поэтому будут возвращены неверные результаты.
Если вы идете по этому маршруту, либо очень убедитесь, что dicts никогда не изменится после того, как они были помещены в другой словарь, или активно их предотвращают (например, проверьте, что хэш никогда не изменяется после сначала вызовите __hash__
и выкиньте исключение, если нет.)
Ответ 4
Хм, это не ваш случай использования, просто напоминающий вызовы функций? Используя декоратор, вы сможете легко поддерживать произвольные функции. И да, они часто разбирают аргументы и используют круговые рассуждения, это работает для нестандартных типов, если их можно мариновать.
См. этот образец memoization
Ответ 5
Чтобы превратить someDictionary в ключ, сделайте это
key = tuple(sorted(someDictionary .items())
Вы можете легко отменить это с помощью dict( key )
Ответ 6
Я не понимаю, почему вы когда-нибудь захотите это сделать, но если вам действительно нужно это сделать, вы можете попробовать забрать словарь:
mydict = {"a":1, "b":{"c":10}}
import pickle
key = pickle.dumps(mydict)
d[key] = value
Ответ 7
эта функция преобразует вложенный словарь в неизменный набор кортежей, который вы можете использовать в качестве ключа:
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()))
Ответ 8
Я не знаю, правильно ли я понимаю ваш вопрос, но я попробую его
d[repr(a)]=value
Вы можете взаимодействовать со словарем следующим образом
for el1 in d:
for el2 in eval(el1):
print el2,eval(el1)[el2]