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

Что такое хешируемые типы данных?

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

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

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

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

Хешируемые типы данных в Python

Хешируемый объект — это объект, который имеет значение хеша (hash value) и может быть использован как ключ в словаре или элемент во множестве (set). Хешируемость — фундаментальное свойство в Python, определяющее, где и как объект может быть применён.

Определение и критерии хешируемости

Объект считается хешируемым, если:

  1. Он имеет метод __hash__() — возвращает целое число
  2. Он неизменяем — его значение не может измениться после создания
  3. Объекты с одинаковым значением имеют одинаковый хеш — если 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

Практические следствия

  1. Производительность поиска: Словари и множества используют хеш для быстрого поиска (O(1) в среднем)
  2. Кэширование: Хешируемые объекты можно использовать с functools.lru_cache
  3. Кортежи как ключи: Кортежи из неизменяемых данных идеальны для составных ключей

Хешируемость — это не просто теоретическая концепция, а практическое требование для работы с основными структурами данных Python.