Какие типы данных могут быть ключами в словарях Python?

Ответ

В Python ключом словаря может быть любой хешируемый (immutable) объект. Это означает, что объект должен быть неизменяемым и иметь метод __hash__(), который возвращает постоянное значение на протяжении его жизни. Хешируемость необходима для эффективной работы словарей, так как они используют хеш-таблицы для быстрого поиска ключей.

Допустимые хешируемые типы данных:

  • Числа: int, float, complex
  • Строки: str
  • Кортежи: tuple, но только если все их элементы также хешируемы.
  • Замороженные множества: frozenset
  • Булевы значения: bool
  • NoneType: None

Недопустимые (нехешируемые) типы данных:

  • Списки: list (изменяемые)
  • Словари: dict (изменяемые)
  • Множества: set (изменяемые)

Пример:

# Допустимые ключи
valid_dict = {
    42: "Ответ на всё",
    "key": "value",
    (1, 2): "tuple as key",
    frozenset({1, 2}): "frozenset as key",
    None: "None as key"
}
print(valid_dict)

# Ошибка: TypeError: unhashable type: 'list'
try:
    invalid_dict = { [1, 2]: "list as key" }
except TypeError as e:
    print(f"Ошибка: {e}")

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

Ответ 18+ 🔞

А, слушай, про ключи в питоновских словарях! Это ж классика, блядь. Сидишь такой, пишешь код, и тут — бац! — TypeError: unhashable type: 'list'. И ты сидишь, ебать мои старые костыли, и думаешь: «Ну что за хуйня? Я ж просто хотел список в ключи запихнуть!»

Так вот, вся соль в том, что ключом может быть только хешируемый объект. Это такой, который не меняется со временем и у которого есть своя цифровая печать — хеш. Словарь по этой печати быстро находит, где что лежит. Представь, как будто ты ищешь книгу в библиотеке не по названию, а по отпечатку пальца на обложке. Если обложку менять каждый день — нихуя не найдёшь, верно?

Что можно пихать в ключи (эти ребята — неизменяемые и с печатью):

  • Числа всякие: int, float, complex — стоят как вкопанные.
  • Строки: str — тоже никуда не денутся.
  • Кортежи: tuple — но только если ВСЁ, что внутри них, тоже хешируемое! Если в кортеже затесался список — пиши пропало, весь кортеж становится негодным.
  • Замороженные множества: frozenset — да, это как set, но его в морозилку отправили, он теперь каменный.
  • Булевы значения: boolTrue или False, без вариантов.
  • NoneType: None — пустота, но тоже со своим местом.

А что НЕЛЬЗЯ (эти — вертлявые и без печати):

  • Списки: list — их можно вечно менять, растягивать, сокращать. Кто ж такую непостоянную сущность в ключи поставит?
  • Словари: dict — сами словари! Ирония, блядь.
  • Множества: set — такие же непостоянные, как и списки.

Смотри, как на практике:

# Вот это — легально, всё прилично
normal_dict = {
    42: "Тот самый ответ, да",
    "ключик": "замочек",
    (1, 2, 3): "кортеж работает",
    frozenset([5, 6]): "замороженный сет",
    None: "ничего"
}
print(normal_dict)

# А вот это — пиздец и ошибка
try:
    govno_dict = { [1, 2, 3]: "список как ключ" }
except TypeError as e:
    print(f"Ошибка, ёпта: {e}")  # Выведет что-то вроде: Ошибка, ёпта: unhashable type: 'list'

И да, чувак, не забудь: ключи в словаре должны быть уникальными. Если ты попробуешь второй раз записать по тому же ключу — старое значение просто накроется медным тазом, его как не бывало. Словарь такой: «О, этот отпечаток пальца я уже видел. Затираю старое, пишу новое. Да похуй».