Функция Python hash(): хэширование объекта

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

Hash функция

Функция Python hash()

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

Укажем, что может означать фиксированный хэш?

  1. Одни и те же данные будут иметь одинаковое значение хэш-функции.
  2. Даже незначительное изменение исходных данных может привести к совершенно другому значению хэш-функции.
  3. Хэш получается из хеш-функции, которая отвечает за преобразование части заданной информации в закодированный хэш.
  4. Несколько объектов могут иметь намного больше, чем несколько хэш-значений, поэтому два объекта могут хэшироваться до одного и того же хэш-значения. Это называется коллизией хэшей. Это означает, что если два объекта имеют одинаковый хэш-код, они не обязательно имеют одинаковое значение.
  5. Объекты, хешированные с помощью hash(), необратимы, что приводит к потере информации.
  6. Метод hash() возвращает хешированные значения только для неизменяемых объектов. Следовательно, его можно использовать в качестве индикатора для проверки изменяемых/неизменяемых объектов.

Внутри метод hash() вызывает метод __hash__() объекта, который установлен по умолчанию для любого объекта. Мы рассмотрим это позже.

Хэш-коды чаще всего используются при сравнении ключей словаря. Хэш-код ключей словаря сравнивается, когда для конкретного ключа выполняется поиск в словаре. Сравнение хэша происходит намного быстрее, чем сравнение всех значений ключа, поскольку набор целых чисел, который хэш-функция отображает каждый ключ словаря, намного меньше, чем сам набор объектов.

Синтаксис

См. приведенный ниже синтаксис метода хэширования.

Параметры

Параметр объекта, хэш-значение которого должно быть возвращено (integerstringfloat).

См. приведенный ниже пример кода.

См. приведенный ниже вывод.

Пример хеш-функции Python

Кортеж — это неизменяемый объект, то есть мы можем создать хэш-значение из кортежа. Список — это изменяемый объект. Вот почему он выдает ошибку, как будто мы можем преобразовать список в хэш. Список является нехешируемым типом.

Возвращаемое значение из hash()

Функция hash() возвращает хэш-значение объекта, если оно есть. Если у объекта есть собственный метод __hash__(), он усекает возвращаемое значение до размера Py_ssize_t.

Как hash() работает в Python

См. следующий пример хэша в python.

В приведенном выше коде мы взяли два типа данных.

  1. Integer
  2. Float

Теперь хэш целого числа — это само целое число, но хэш числа с плавающей запятой несколько отличается. Например, см. приведенный ниже вывод.

Как hash() работает в Python

Python hash() String

Давайте начнем создавать простые примеры и сценарии, в которых метод hash() может быть полезен.

В этом примере мы получим хэш-значение строки.

См. приведенный ниже вывод.

хэш-значение строки

Оба вывода одинаковы, потому что мы использовали одну и ту же строку для хэша.

Вот существенная загвоздка: если вы повторно запустите тот же скрипт, хэш изменится, как показано ниже.

вывод

Как определить функцию hash() для пользовательских объектов

Функция hash() переопределяет функцию __hash()__. Стоит заметить, что не каждый объект можно хэшировать (изменяемые коллекции не хэшируются).

Мы также можем определить функцию __hash__() для нашего пользовательского класса. Но перед этим отметим несколько существенных моментов.

См. следующий пример.

  1. Хэшируемая реализация не должна выполняться для изменяемых коллекций, так как ключи коллекций должны быть неизменяемыми для хеширования.
  2. Нам не нужно определять собственную реализацию функции __eq()__, так как она определена для всех объектов.

См. следующий пример кода.

Вывод:

определить функцию для пользовательских объектов

Кейсы для реализации пользовательского хэша для объектов.

Хэш-реализация объектов

__eq__() __hash__() Описание
Определено(по умолчанию) Определено(по умолчанию) Если оставить как есть, все объекты сравниваются неравными(кроме самих себя)
(Если изменяемый) Определено Не следует определять Реализация хэшируемой коллекции требует, чтобы хэш-значение ключа было неизменным.
Не определено Не следует определять Если __eq__() не определено, __hash__() не следует определять.
Определено Не определено Экземпляры класса нельзя использовать в качестве хэшируемой коллекции.

__hash__() неявно установлено в None.

Вызывает исключение TypeError при попытке получить хэш.

Определено Удержать от родителя __hash__ = <ParentClass>.__hash__
Определено Не хочет хешировать __hash__ = None

Вызывает исключение TypeError при попытке получить хэш.

Почему изменяемый объект нельзя хэшировать

Как мы уже знаем, хэшировать можно только неизменяемый объект. Это ограничение, запрещающее хеширование изменяемого объекта, значительно упрощает хеш-таблицу. Разберемся как.

Если изменяемый объект разрешено хэшировать, нам нужно обновлять хэш-таблицу каждый раз, когда значение объекта обновляется. Это означает, что нам придется переместить объект. Это очень дорогостоящая операция.

В Python у нас есть два объекта, которые используют хэш-таблицы, словари и наборы:

  1. Словарь представляет собой хеш-таблицу и называется ассоциативным массивом. В словаре хэшируются только ключи, а не значения. Вот почему ключ словаря также должен быть неизменяемым объектом, а значениями может быть что угодно, даже изменяемый список.
  2. Набор содержит уникальные объекты, которые можно хэшировать. Если у нас есть нехэшируемые элементы, мы не можем использовать набор и вместо этого используем список.
Оцените статью

Автор статей и разработчик, делюсь знаниями.

Программирование на Python