Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Хешируемые типы данных в Python
Хешируемый объект — это объект, который имеет значение хеша (hash value) и может быть использован как ключ в словаре или элемент во множестве (set). Хешируемость — фундаментальное свойство в Python, определяющее, где и как объект может быть применён.
Определение и критерии хешируемости
Объект считается хешируемым, если:
- Он имеет метод
__hash__()— возвращает целое число - Он неизменяем — его значение не может измениться после создания
- Объекты с одинаковым значением имеют одинаковый хеш — если
a == b, тоhash(a) == hash(b)
Встроенные хешируемые типы
Неизменяемые типы (immutable):
# Целые числа
x = 42
print(hash(x)) # хешируемо
# Строки
s = "hello"
print(hash(s)) # хешируемо
# Кортежи (если содержат только хешируемые элементы)
t = (1, 2, 3)
print(hash(t)) # хешируемо
t_with_list = (1, [2, 3]) # список внутри
# TypeError: unhashable type: list
# None
print(hash(None)) # хешируемо
# Булевы значения
print(hash(True)) # хешируемо
# Frozenset
fs = frozenset([1, 2, 3])
print(hash(fs)) # хешируемо
Встроенные нехешируемые типы
Изменяемые типы (mutable):
# Списки
lst = [1, 2, 3]
print(hash(lst)) # TypeError: unhashable type: list
# Словари
d = {"key": "value"}
print(hash(d)) # TypeError: unhashable type: dict
# Множества (обычные)
s = {1, 2, 3}
print(hash(s)) # TypeError: unhashable type: set
Использование в качестве ключей словаря
# Хешируемые объекты — идеальные ключи
data = {}
data[42] = "число"
data["string"] = "строка"
data[(1, 2)] = "кортеж"
print(data) # {42: число, string: строка, (1, 2): кортеж}
# Нехешируемые объекты вызовут ошибку
# data[[1, 2, 3]] = "список" # TypeError: unhashable type: list
Использование во множестве (set)
# Можно добавлять только хешируемые объекты
unique_values = {1, 2, "hello", (3, 4), None}
print(unique_values) # {1, 2, hello, (3, 4), None}
# Попытка добавить нехешируемый объект
# unique_values.add([1, 2]) # TypeError: unhashable type: list
Создание собственного хешируемого класса
class Point:
def __init__(self, x, y):
self._x = x
self._y = y
def __eq__(self, other):
if not isinstance(other, Point):
return False
return self._x == other._x and self._y == other._y
def __hash__(self):
return hash((self._x, self._y))
def __repr__(self):
return f"Point({self._x}, {self._y})"
# Использование
point1 = Point(1, 2)
point2 = Point(1, 2)
point3 = Point(2, 3)
print(point1 == point2) # True
print(hash(point1) == hash(point2)) # True
# Можно использовать как ключ
point_data = {point1: "центр"}
print(point_data[point2]) # "центр" (так как point1 == point2)
# И во множествах
points = {point1, point2, point3}
print(len(points)) # 2 (point1 и point2 считаются одинаковыми)
Важные принципы
# Принцип: если переопределяешь __eq__, должен переопределить __hash__
class BadExample:
def __init__(self, value):
self.value = value
def __eq__(self, other):
return self.value == other.value
# Без __hash__ объект становится нехешируемым
bad = BadExample(5)
print(hash(bad)) # TypeError: unhashable type: BadExample
Практические следствия
- Производительность поиска: Словари и множества используют хеш для быстрого поиска (O(1) в среднем)
- Кэширование: Хешируемые объекты можно использовать с
functools.lru_cache - Кортежи как ключи: Кортежи из неизменяемых данных идеальны для составных ключей
Хешируемость — это не просто теоретическая концепция, а практическое требование для работы с основными структурами данных Python.