Ответ
В Python ключом словаря (dict) может быть любой хешируемый (hashable) тип данных. Хешируемость означает, что объект имеет неизменяемое значение, которое может быть использовано для вычисления уникального хеша.
Главное правило: Ключ должен быть неизменяемым (immutable) типом.
Допустимые типы ключей (хешируемые и неизменяемые):
- Числа:
int,float,complex,bool(True/False). - Строки:
str. - Кортежи (tuple): Но только если все элементы кортежа сами являются хешируемыми.
frozenset: Неизменяемая версия множества.bytes.
Недопустимые типы ключей (нехешируемые и изменяемые):
- Списки (
list). - Словари (
dict). - Множества (
set). - Большинство пользовательских классов (по умолчанию хешируемы, но могут стать нехешируемыми, если реализуют
__eq__без__hash__или являются изменяемыми).
Примеры на практике:
# ДОПУСТИМЫЕ ключи:
valid_dict = {
42: 'integer key',
3.14: 'float key',
'name': 'string key',
(1, 2, 3): 'tuple key', # Кортеж из чисел
(1, 'a', (2, 3)): 'complex tuple', # Кортеж с вложенным кортежем
frozenset([1,2]): 'frozenset key',
True: 'boolean key'
}
print(valid_dict[(1, 2, 3)]) # Вывод: tuple key
# НЕДОПУСТИМЫЕ ключи (вызовут TypeError: unhashable type):
try:
invalid_dict = {
[1, 2]: 'list key', # Список - ИЗМЕНЯЕМЫЙ
{1, 2}: 'set key', # Множество - ИЗМЕНЯЕМОЕ
{'a': 1}: 'dict key' # Словарь - ИЗМЕНЯЕМЫЙ
}
except TypeError as e:
print(f'Ошибка: {e}')
Почему важна неизменяемость? Хеш ключа вычисляется один раз при его добавлении в словарь и используется для быстрого поиска значения. Если бы ключ мог измениться, его хеш также изменился бы, и найти связанное с ним значение стало бы невозможно, что нарушило бы целостность структуры данных.
Ответ 18+ 🔞
А, слушай, про ключи в питоновских словарях! Ну это, блядь, целая наука, но если по-простому, то запомни раз и навсегда, как мантру: ключ должен быть неизменяемым и хешируемым.
Что это значит на языке нормальных людей? А значит это, что ключ — это как отпечаток пальца, ёпта. Его вычислили один раз, запомнили, и всё, трогать его нельзя. Если он поменяется — пиши пропало, словарь его уже не узнает, и твоё значение нахуй потеряется в недрах оперативки.
Что можно пихать в ключи (или "что не сломается"):
- Циферки всякие:
42,3.14, дажеTrueсFalse(это ж те же единичка с ноликом по сути). - Буквы (строки):
'привет','key'— их не изменишь, они как есть. - Кортежи (
tuple): Вот это хитрая жопа! Можно, но только если внутри кортежа тоже сидят святые, то есть другие неизменяемые штуки.(1, 2, 'a')— ок.(1, [2,3])— уже пиздец, потому что внутри спишок изменяемый засел. frozenset: Это такой замороженныйset, его не разморозишь, не изменишь — идеальный кандидат.bytes: Ну, байты, чё.
Что НЕЛЬЗЯ пихать в ключи (или "что вызовет TypeError: unhashable type и все засмеются"):
- Списки (
list): О, нет-нет-нет! Сегодня[1, 2], завтраappend(3)— и всё, ключ поехал, словарь в ауте. - Словари (
dict): Да ты что, блядь! Сам словарь хочет стать ключом в другом словаре? Цирк с конями! Они же изменяемые, как мартышлюшки. - Множества (
set): Та же история — добавил элемент, и хеш поменялся. Нахуй так нельзя. - Твои кастомные классы: По умолчанию-то можно, но если ты начнёшь там
__eq__городить без__hash__, или класс твой будет меняться как погода в Питере — всё, приехали, нехешируемый.
Смотри, как на практике:
# Всё работает, все довольны
normalny_dict = {
42: 'ключ-число',
3.14: 'ключ с плавающей запятой, блядь',
'имя': 'строковый ключ',
(1, 2, 3): 'кортежный ключ', # Кортеж из циферок
(1, 'а', (2, 3)): 'сложный кортеж', # Внутри ещё кортеж сидит
frozenset([1,2]): 'ключ из заморозки',
True: 'булевый ключ'
}
print(normalny_dict[(1, 2, 3)]) # Напечатает: кортежный ключ
# А вот тут сейчас будет магия и пиздец
try:
govnokod_dict = {
[1, 2]: 'ключ-список', # СПИСОК! ИЗМЕНЯЕМЫЙ! НЕ-НЕ-НЕ!
{1, 2}: 'ключ-множество', # МНОЖЕСТВО! ТОЖЕ ИЗМЕНЯЕМОЕ!
{'a': 1}: 'ключ-словарь' # СЛОВАРЬ В КЛЮЧЕ СЛОВАРЯ, ЁПТА!
}
except TypeError as e:
print(f'Ошибка, как и ожидалось: {e}') # И получишь свои законные грабли по лбу
А почему, спрашивается, такая хуйня? Да потому что словарь — это умная структура, она по хешу ключа мгновенно находит твоё значение. Представь, ты пришёл в гардероб, сдал пальто (ключ 'хуй в пальто'), тебе дали номерок (хеш). А потом ты это пальто (ключ) перешил в куртку. Приходишь с номерком, а куртку тебе не отдают — "не, мужик, у нас тут пальто числится". Вот и словарь так же: изменился ключ — хеш не совпал, значение потерял. Поэтому только неизменяемое, блядь, только хардкор!