Использование словаря Python в качестве ключа (не вложенного)

Python не позволяет использовать словари в качестве ключей в других словарях. Есть ли способ обхода без вложенных словарей в качестве ключей?

Общая проблема с более сложными не-хэшируемыми объектами и моим конкретным вариантом использования была перенесена здесь. Мое первоначальное описание моего варианта использования было неправильным.

Ответ 1

Если у вас есть действительно неизменный словарь (хотя мне не понятно, почему вы не просто используете список пар: например, [('content-type', 'text/plain'), ('host', 'example.com')]), тогда вы можете преобразовать ваш dict в:

  1. Кортеж пар. Вы уже сделали это в своем вопросе. Вместо list требуется tuple потому что результаты зависят от упорядоченности и неизменности элементов.

    >>> tuple(sorted(a.items()))
    
  2. Замороженный набор. Это более подходящий подход с математической точки зрения, так как она требует только отношение равенства на элементах вашего неизменного 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]