Использование словаря Python в качестве ключа (не вложенный) - PullRequest
22 голосов
/ 21 октября 2009

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

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

Ответы [ 8 ]

54 голосов
/ 21 октября 2009

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

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

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

    >>> frozenset(a.items())
    
8 голосов
/ 21 октября 2009

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

Может оказаться полезным этот вопрос SO: Каков наилучший способ реализации вложенных словарей?

А вот пример модуля сглаживания, который сгладит словари: http://yawpycrypto.sourceforge.net/html/public/Flatten.Flatten-module.html

Я не совсем понимаю ваш вариант использования и подозреваю, что вы пытаетесь преждевременно оптимизировать то, что не требует оптимизации.

4 голосов
/ 21 октября 2009

Один из способов сделать это - создать подкласс 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__ и, если нет, сгенерируйте исключение.)

3 голосов
/ 21 октября 2009

Хм, разве ваш случай использования не запоминает вызовы функций? Используя декоратор, вы будете легко поддерживать произвольные функции. И да, они часто перебирают аргументы, и, используя циклические рассуждения, это работает для нестандартных типов, если их можно перебрать.

Смотри, например, этот образец памятки

2 голосов
/ 21 октября 2009

Чтобы превратить someDictionary в ключ, сделайте это

key = tuple(sorted(someDictionary .items())

Вы можете легко изменить это с помощью dict( key )

0 голосов
/ 29 ноября 2018

эта функция преобразует вложенный словарь в неизменный набор кортежей, который вы можете использовать в качестве ключа:

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()))
0 голосов
/ 21 октября 2009

Не знаю, правильно ли я понимаю ваш вопрос, но попробую

    d[repr(a)]=value

Вы можете использовать словарь как этот

for el1 in d:
        for el2 in eval(el1):
                print el2,eval(el1)[el2]
0 голосов
/ 21 октября 2009

Я не понимаю, почему вы когда-нибудь захотите это сделать, но если вам действительно это нужно, вы можете попробовать выбрать словарь:

mydict = {"a":1, "b":{"c":10}}
import pickle
key = pickle.dumps(mydict)

d[key] = value
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...