Что такое хэшируемые типы данных?
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, так как объекты равны и хэшируемы