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

StackOverflow https://stackoverflow.com/questions/1600591

Вопрос

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]
    
    Лицензировано под: CC-BY-SA с атрибуция
    Не связан с StackOverflow
    scroll top