Почему я не могу использовать список в качестве ключа dict в python?

Я немного смущен тем, что нельзя / не может использовать в качестве ключа для питона-диктата.

dicked = {} dicked[None] = 'foo' # None ok dicked[(1,3)] = 'baz' # tuple ok import sys dicked[sys] = 'bar' # wow, even a module is ok ! dicked[(1,[3])] = 'qux' # oops, not allowed 

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

У меня было какое-то смутное представление о том, что ключ должен быть «хэшируемым», но я просто буду признавать свое невежество в отношении технических деталей; Я не знаю, что здесь происходит. Что пойдет не так, если вы попытаетесь использовать списки в качестве ключей, а хэш, скажем, их место в памяти?

  • Наследование Python - как отключить функцию
  • Как измерить совпадение изображения в оптическом дальномерном
  • Socket.error: недопустимый аргумент
  • Почему экспоненциальная нотация с десятичными значениями не выполняется?
  • Попытка вытащить сообщения и комментарии из Facebook для проекта, но не может получить все (python, json)
  • Используя BeautifulSoup, как защитить от элементов, которые не найдены?
  • Как иметь две модели, ссылки друг на друга Django
  • Различия между STATICFILES_DIR, STATIC_ROOT и MEDIA_ROOT
  • 7 Solutions collect form web for “Почему я не могу использовать список в качестве ключа dict в python?”

    В вики Python есть хорошая статья по этой теме: Почему списки не могут быть ключевыми словами . Как объясняется там:

    Что пойдет не так, если вы попытаетесь использовать списки в качестве ключей, а хэш, скажем, их место в памяти?

    Это можно сделать, не нарушая при этом никаких требований, но это приводит к неожиданному поведению. Списки обычно обрабатываются так, как если бы их значение было получено из значений их содержимого, например, при проверке (in) равенства. Многие могли бы, понятно, ожидать, что вы можете использовать любой список [1, 2] чтобы получить тот же ключ, где вам нужно будет поддерживать точно такой же объект списка. Но поиск по значениям разрывается, как только список, используемый как ключ, изменяется, а для поиска по идентификатору требуется, чтобы вы придерживались точно такого же списка, что не требуется для какой-либо другой операции общего списка (по крайней мере, я не могу думать о ).

    Другие объекты, такие как модули и object в любом случае делают гораздо большую сделку из их идентичности объектов (когда в последний раз у вас были два отдельных объекта модуля, называемых sys ?), И в любом случае их сравнивают. Поэтому менее удивительно или даже ожидать, что они, когда они используются в качестве ключей ключей, сравниваются по идентичности в этом случае.

    Проблема в том, что кортежи неизменяемы, а списки – нет. Рассмотрим следующее

     d = {} li = [1,2,3] d[li] = 5 li.append(4) 

    Что должно вернуть d[li] ? Это тот же список? Как насчет d[[1,2,3]] ? Он имеет те же значения, но другой список?

    В конечном счете, нет удовлетворительного ответа. Например, если единственным ключом, который работает, является исходный ключ, то, если у вас нет ссылки на этот ключ, вы больше никогда не сможете получить доступ к значению. С любым другим разрешенным ключом вы можете создать ключ без ссылки на оригинал.

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

    Почему я не могу использовать список в качестве ключа dict в python?

     >>> d = {repr([1,2,3]): 'value'} {'[1, 2, 3]': 'value'} 

    (для любого, кто спотыкается на этот вопрос, ищет способ обойти его)

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

    Вот ответ http://wiki.python.org/moin/DictionaryKeys

    Что пойдет не так, если вы попытаетесь использовать списки в качестве ключей, а хэш, скажем, их место в памяти?

    Поиск разных списков с одним и тем же содержимым приведет к различным результатам, хотя сравнение списков с одним и тем же содержимым означает их эквивалент.

    Как использовать литерал списка в словаре?

    Ваш тент можно найти здесь:

    Почему списки не могут быть ключевыми словами

    Новички на Python часто задаются вопросом, почему, в то время как язык включает как кортеж, так и тип списка, кортежи можно использовать в качестве словарных клавиш, а списки – нет. Это было преднамеренное дизайнерское решение, и его лучше всего объяснить, если сначала понять, как работают словари Python.

    Источник и дополнительная информация: http://wiki.python.org/moin/DictionaryKeys

    Простой ответ на ваш вопрос заключается в том, что список классов не реализует хэш метода, который требуется для любого объекта, который хочет использоваться в качестве ключа в словаре. Однако причина, почему хеш не реализована так же, как и в том случае, если класс кортежа (на основе содержимого контейнера) заключается в том, что список изменен, поэтому для редактирования списка потребуется перерасчет хеша, который может означать список в теперь находится в неправильном ковше в таблице хэширования underling. Обратите внимание, что, поскольку вы не можете изменить кортеж (неизменный), он не сталкивается с этой проблемой.

    В качестве дополнительной заметки фактическая реализация поиска dictobjects основана на алгоритме D от Knuth Vol. 3, гл. 6.4. Если у вас есть эта книга для вас, это может быть полезно прочитать, кроме того, если вы действительно заинтересованы, вы можете взглянуть на комментарии разработчика о фактической реализации dictobject здесь. Он подробно рассказывает о том, как это работает. Существует также лекция python о реализации словарей, которые могут вас заинтересовать. Они проходят определение ключа и то, что происходит в первые несколько минут.

    Согласно документации Python 2.7.2:

    Объект hashable, если он имеет хеш-значение, которое никогда не изменяется в течение его жизненного цикла (ему нужен метод hash ()), и его можно сравнить с другими объектами (ему нужен метод eq () или cmp ()). Объекты Hashable, которые сравнивают одинаковые, должны иметь одно и то же значение хэш-функции.

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

    Все неизменяемые встроенные объекты Python являются хешируемыми, в то время как не изменяемые контейнеры (например, списки или словари). Объекты, являющиеся экземплярами пользовательских классов, по умолчанию хешируются; все они сравниваются неравномерно, а их хеш-значение – их id ().

    Кортеж неизменен в том смысле, что вы не можете добавлять, удалять или заменять его элементы, но сами элементы могут быть изменчивыми. Значение хеша списка зависит от хэш-значений его элементов и поэтому изменяется при изменении элементов.

    Использование хэшей списка id для списка будет означать, что все списки сравниваются по-разному, что было бы удивительно и неудобно.

    Python - лучший язык программирования в мире.