Назад к вопросам
Junior
69
questionbank

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

Sobes Copilot

Получайте ответы в реальном времени

Ответ от нейросети

sobes.tech AI

Хэшируемые типы данных в Python — это неизменяемые типы, экземпляры которых имеют фиксированное хэш-значение на протяжении всего своего жизненного цикла. Это значение вычисляется с помощью хэш-функции и используется для быстрого поиска элементов в множествах (sets) и ключей в словарях (dictionaries).

Свойства хэшируемых типов:

  • Неизменяемость: Объект не может быть изменен после создания.
  • **Наличие метода __hash__: ** Этот метод должен возвращать целочисленное хэш-значение объекта. Если метод не определен или возвращает None, объект считается нехэшируемым.
  • **Наличие метода __eq__: ** Этот метод должен определять равенство объектов. Если два объекта равны (a == b), то их хэш-значения должны быть равны (hash(a) == hash(b)). Обратное неверно: два объекта могут иметь одинаковое хэш-значение, но быть неравными (коллизия хэшей).

Примеры хэшируемых встроенных типов:

  • Числа (int, float, complex):
    # Примеры
    print(hash(123))
    print(hash(3.14))
    print(hash(1 + 2j))
    
  • Строки (str):
    # Пример
    print(hash("hello"))
    
  • Кортежи (tuple): При условии, что все элементы кортежа хэшируемы.
    # Пример
    print(hash((1, 2, "a")))
    
  • Булевы значения (bool):
    # Пример
    print(hash(True))
    
  • NoneType:
    # Пример
    print(hash(None))
    

Примеры нехэшируемых встроенных типов:

  • Списки (list): Изменяемы.
    # Пример
    # list = [1, 2]
    # print(hash(list)) # Вызовет TypeError
    
  • Множества (set): Изменяемы.
    # Пример
    # my_set = {1, 2}
    # print(hash(my_set)) # Вызовет TypeError
    
  • Словари (dict): Изменяемы.
    # Пример
    # my_dict = {"a": 1}
    # print(hash(my_dict)) # Вызовет TypeError
    

Использование хэшируемых типов:

  • Ключи словаря должны быть хэшируемыми.
    # Пример
    my_dict = {"apple": 1, (1, 2): 2} # Допустимо
    # my_dict = {[1, 2]: 3} # Недопустимо, вызовет TypeError
    
  • Элементы множества должны быть хэшируемыми.
    # Пример
    my_set = {"a", 1, (2, 3)} # Допустимо
    # my_set = {"a", [1, 2]} # Недопустимо, вызовет TypeError
    

Пользовательские классы по умолчанию хэшируемы, если они наследуют от класса, который определяет __hash__, или если они не определяют методов __eq__ и __hash__. Если определен только __eq__, класс становится нехэшируемым. Можно сделать пользовательский класс хэшируемым, определив методы __eq__ и __hash__ таким образом, чтобы они соответствовали своим требованиям. Для неизменяемых объектов можно использовать декоратор @total_ordering в сочетании с определением __eq__ и других методов сравнения.

# Пример пользовательского неизменяемого и хэшируемого класса
from functools import total_ordering

@total_ordering
class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __eq__(self, other):
        if not isinstance(other, Point):
            return NotImplemented
        return self.x == other.x and self.y == other.y

    def __hash__(self):
        # Хэш кортежа, содержащего хэши элементов
        return hash((self.x, self.y))

# Использование в словаре
p1 = Point(1, 2)
p2 = Point(1, 2)
my_dict = {p1: "coordinates"}
print(p2 in my_dict) # True, так как объекты равны и хэшируемы