Ответ
Хешируемый (hashable) объект в Python — это объект, который можно использовать в качестве ключа в словаре (dict) или элемента множества (set). Главное свойство такого объекта — наличие неизменяемого хеш-значения на протяжении всего его жизненного цикла.
Основные требования к хешируемому объекту:
- Реализация
__hash__(): Метод должен возвращать целочисленное значение (int). Для одного и того же объекта он всегда должен возвращать одинаковый хеш. - Реализация
__eq__(): Метод необходим для сравнения объектов. Если два объекта равны (a == bистинно), то их хеши также должны быть равны (hash(a) == hash(b)).
Почему это важно?
Словари и множества используют хеш для быстрого поиска. Сначала вычисляется хеш ключа, чтобы найти нужную "корзину" (bucket), а затем используется __eq__() для поиска конкретного элемента среди всех объектов в этой корзине (в случае коллизии).
Примеры:
- Хешируемые типы (неизменяемые):
int,float,str,tuple,frozenset. - Нехешируемые типы (изменяемые):
list,dict,set.
# Хешируемый тип (tuple)
hashable_key = (1, 'a')
my_dict = {hashable_key: 'some_value'}
print(f"Словарь с tuple-ключом: {my_dict}")
# Попытка использовать нехешируемый тип (list)
unhashable_key = [1, 'a']
try:
another_dict = {unhashable_key: 'another_value'}
except TypeError as e:
print(f"Ошибка: {e}")
Вывод:
Словарь с tuple-ключом: {(1, 'a'): 'some_value'}
Ошибка: unhashable type: 'list' Ответ 18+ 🔞
А, ну вот, опять про эти хешируемые объекты, блядь. Слушай, это ж основа основ, а народ как будто в рот мне чих-пых, не понимает, что к чему.
Короче, представь себе, что у тебя есть словарь — это такой шкаф с ящиками, ёпта. А ключ от ящика — это и есть твой хешируемый объект. Если ключ кривой, из говна и палок слеплен, то ты этот ящик никогда не откроешь, или хуже того, откроешь, а там не твоё барахло.
Так вот, чтобы ключ был годный, он должен соблюдать два правила, блядь, железных:
-
У него должен быть метод
__hash__(). Это как серийный номер на ключе, целое число. И главное, сука, чтобы этот номер не менялся, пока ключ живёт. Представь, ты пришёл к шкафу, номер на ключе 123, открыл ящик. Пришёл на следующий день, а на ключе уже 456. Ну и как, блядь, ты теперь свой ящик найдёшь? Пиздец. -
У него должен быть метод
__eq__(). Это для сравнения, когда два ключа в одну корзину попадают (коллизия, блядь, называется). Если два ключа равны (a == b), то и хеши у них должны быть одинаковые, а то получится ебаный цирк: ключи одинаковые, а открывают разные ящики. Волнение ебать, терпения ноль.
Кто годный, а кто — мудя?
- Годные (неизменяемые):
int,str,tuple,frozenset. Как отлитые из стали, блядь. Раз создал — и хеш вечный. - Мудя (изменяемые):
list,dict,set. Сегодня он один, завтра ты в него что-то добавил, хеш поменялся, и всё, пидары налетели, структура данных ебнулась.
# Вот смотри, кортеж — красава, хешируется
norm_key = (1, 'a')
my_cool_dict = {norm_key: 'значение'}
print(f"Всё ок: {my_cool_dict}")
# А теперь список, пидарас шерстяной
bad_key = [1, 'a']
try:
fail_dict = {bad_key: 'пиздец'}
except TypeError as e:
print(f"Ну вот, обосрались: {e}") # Справедливо скажет "unhashable type: 'list'"
Вывод-то какой будет? Правильный, блядь:
Всё ок: {(1, 'a'): 'значение'}
Ну вот, обосрались: unhashable type: 'list'
Вот и вся философия. Не хочешь проблем — делай ключи из того, что не ломается. А то будешь потом как Герасим, с мешком на озере стоять и думать: «Что же я, мудак, сделал?».