← Назад к вопросам

Может ли list быть ключом в dictionary?

1.0 Junior🔥 121 комментариев
#Другое

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Может ли list быть ключом в dictionary?

Ответ: НЕТ, list не может быть ключом в dictionary.

Попытка использовать list как ключ приведёт к ошибке TypeError: unhashable type: 'list'.

Почему list не может быть ключом?

Dictionary в Python требует, чтобы ключи были hashable (хешируемыми). List является mutable (изменяемым) типом, поэтому Python запрещает его использование как ключ.

Ошибка:

# Попытка использовать list как ключ
my_dict = {}
my_dict[[1, 2, 3]] = "value"  # TypeError: unhashable type: 'list'

Что такое hashable?

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

Hashable типы (можно как ключи):

# int
my_dict = {1: "value"}  # ✓ OK

# str
my_dict = {"name": "John"}  # ✓ OK

# tuple (если содержит только hashable элементы)
my_dict = {(1, 2, 3): "value"}  # ✓ OK

# frozenset (неизменяемая версия set)
my_dict = {frozenset([1, 2]): "value"}  # ✓ OK

# bool, None, float
my_dict = {True: "yes", None: "nothing", 3.14: "pi"}  # ✓ OK

NON-Hashable типы (НЕ можно как ключи):

# list
my_dict = {[1, 2, 3]: "value"}  # ✗ TypeError

# dict
my_dict = {{"a": 1}: "value"}  # ✗ TypeError

# set
my_dict = {{1, 2, 3}: "value"}  # ✗ TypeError

Почему список изменяемый — это проблема?

Представь, что list мог бы быть ключом:

# Гипотетически
my_dict = {}
key = [1, 2, 3]
my_dict[key] = "value"

# Потом кто-то меняет список
key.append(4)  # Список изменился!

# Теперь хеш изменился, и dictionary не может найти ключ
print(my_dict[key])  # Где искать? На нём был хеш для [1,2,3], но теперь [1,2,3,4]

Это нарушает логику dictionary, поэтому Python запрещает изменяемые типы как ключи.

Проверка hashability

Способ 1: Попыться хешировать

# Hashable тип
hash((1, 2, 3))  # 529344067295497451 - работает

# Non-hashable тип
hash([1, 2, 3])  # TypeError: unhashable type: 'list'

Способ 2: Проверить наличие hash метода

print(hasattr((1, 2), "__hash__"))  # True
print(hasattr([1, 2], "__hash__"))  # False

Что делать, если нужен список как ключ?

Вариант 1: Преобразовать в tuple

my_list = [1, 2, 3]
my_dict = {}
my_dict[tuple(my_list)] = "value"

print(my_dict[(1, 2, 3)])  # "value"

Вариант 2: Преобразовать в frozenset (для наборов)

my_list = [1, 2, 3]
my_dict = {}
my_dict[frozenset(my_list)] = "value"

print(my_dict[frozenset([1, 2, 3])])  # "value"

Вариант 3: Использовать строку (если нужно сохранить порядок)

my_list = [1, 2, 3]
key = str(my_list)  # "[1, 2, 3]"
my_dict = {key: "value"}

print(my_dict["[1, 2, 3]"])  # "value"

Вариант 4: Кастомный класс с hash (для сложных структур)

from dataclasses import dataclass

@dataclass(frozen=True)  # frozen=True делает объект hashable
class Point:
    x: int
    y: int

my_dict = {}
key = Point(1, 2)
my_dict[key] = "location"

print(my_dict[Point(1, 2)])  # "location"

Практические примеры

Пример 1: Координаты на сетке

# Плохо: используем список
positions = {}
pos = [10, 20]
positions[tuple(pos)] = "player_1"  # Нужно конвертировать

# Хорошо: используем tuple сразу
positions = {(10, 20): "player_1"}

Пример 2: Кэширование результатов функции

# Функция, которую нужно кэшировать
def calculate(a, b, c):
    return a + b + c

# Кэш как словарь
cache = {}

# Плохо: используем список
# key = [1, 2, 3]
# cache[tuple(key)] = calculate(*key)

# Хорошо: используем tuple
key = (1, 2, 3)
if key not in cache:
    cache[key] = calculate(*key)

result = cache[key]  # 6

Пример 3: Многомерные индексы в матрице

# Матрица как словарь
matrix = {}

# Индексы как tuple
matrix[(0, 0)] = 1
matrix[(0, 1)] = 2
matrix[(1, 0)] = 3

print(matrix[(0, 1)])  # 2

Почему Python сделал list изменяемым, а tuple нет?

List — изменяемый:

my_list = [1, 2, 3]
my_list[0] = 10  # Можно менять
my_list.append(4)  # Можно добавлять
my_list.pop()  # Можно удалять

Tuple — неизменяемый:

my_tuple = (1, 2, 3)
my_tuple[0] = 10  # TypeError!
my_tuple.append(4)  # AttributeError!

Причина: Tuple гарантирует неизменяемость → гарантирует стабильный хеш → может быть ключом.

Таблица хешируемости

ТипHashable?Может быть ключом?Причина
intНеизменяемый примитив
strНеизменяемый примитив
floatНеизменяемый примитив
tupleНеизменяемая последовательность
frozensetНеизменяемое множество
boolНеизменяемый примитив
NoneНеизменяемый объект
listИзменяемая последовательность
dictИзменяемый контейнер
setИзменяемое множество
bytearrayИзменяемая последовательность

Вывод

List НЕ может быть ключом в dictionary потому что:

  1. List — изменяемый тип данных
  2. Dictionary требует, чтобы ключи были hashable
  3. Изменяемые типы не имеют стабильного хеша
  4. Если ключ изменится, dictionary не сможет его найти

Решение: Используй tuple вместо list для использования как ключ, так как tuple неизменяем и hashable.