#16. Магические методы __eq__ и __hash__ | Объектно-ориентированное программирование Python

preview_player
Показать описание

Что такое хэш объектов классов, как вычисляется и для чего нужен. Переопределение стандартного поведения функции hash() через магические методы __eq__ и __hash__.

Рекомендации по теме
Комментарии
Автор

Блин! Надо было мне сначала с Вашего курса начать! Обучение пошло бы быстрее и без головной боли. Братцы, давайте "подналягем" лайками и коментами, надо это сокровище в массы двигать!

nityull
Автор

просто взрыв мозга, сколько пользы, помноженной на краткость, наглядность и простоту изложения

yoruwamatahajimaru
Автор

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

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

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

g.s
Автор

Благодаря этому уроку, я понял как работают словари. Спасибо

danielfessow
Автор

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

umion
Автор

Господи спасибо! Я наконец понял, что такое хеш и как зачем он нужен)

borys.bond_
Автор

А вот так просто на раз-два автор объясняет идею хеш-таблиц. Читать и разбираться в ней гораздо дольше. Браво!

bwinyos
Автор

0:20 К изменяемым объектам тоже можно примерить hash()
В пользовательском классе, например.
У одинаковых объектов хеш может быть разным.
Функция __hash__ будет запускаться во время добавления ключа словаря
import random

class HashTest:
def __hash__(self):
print("hash")
return random.randint(0, 100)
def __repr__(self):
return "Info"
I = HashTest()
print({I:"One", I:"Two", I:"Three"})


Посмотри чо будет.
У КАЖДОГО ОБЪЕКТА в питоне есть метод __hash__ т.к. он есть у класса object от которого унаследованны все остальные. Но не хешируемыми объектами являеются те, у кого __hash__ = None
Попробуй удалить функцию __hash__ из моего примера, написать __hash__ = None, а остальное оставить как есть - и будет ошибка unhashable type

gferugg
Автор

Такое чувство, что мы потихоньку создаем классические объекты питон, у которых будут все встроенные функции

MrCipec
Автор

Добрый вечер, как поступать в таком случае, если при сравнениях, я хочу сравнивать именно экземпляры двух классов и для этого соотвественно прописываю метод __eq__, который мне их и сравнивает, в случае, если попадается не экземпляр класса, а какой-то другой тип данных, генерирует ошибку. Тогда при создание словаря, допустим d, и последующем создание ключа d[p1], потом при создание ключа d[(1, 2)] (числа такие же, как и координаты точек в p1), будет генерироваться ошибка, что второй операнд должен быть класса Point, хотя с логической точки зрения, такой ошибки появляться не должно.

lyjhpcz
Автор

У меня вопрос, если определить класс в котором определены методы для изменения значения объектов например __add__ или __sub__, то будет ли этот объект восприниматься как неизменяемый?

bych_
Автор

У меня вопрос возник: вы сказали что при поиске в словаре сначала ведется поиск по хэшу, а затем, если хэши равны сравниваются сами ключи. а как в словаре могут оказаться ключи с одинаковым хэшем? при создании словаря получается?

artur.tokranov
Автор

Получается изменение метода __eq__ влияет на работу метода __hash__. А обратная зависимость есть? Если поменять __hash__ изменится ли работа __eq__?

yusqfce
Автор

Любопытно. А что если создать класс унаследовавшись от какого-нибудь нехешируемого объекта, например list, и переопределить метод __hash__, то что получится? Хешируемый нехешируемый объект? Это, вообще, будет работать?

nrmaLman
Автор

У меня появился вопрос на эту тему:
Если в методе __eq__ определить логику по которой равенство будет считаться при равенстве какого-то одного элемента из кортежа(например при point1 = Point(1, 2), запись point1 == (1, 10)(или с любым другим кортежем с первым элементом == 1) будет возвращать True), то hash(point1) ((self.x, self.y)) не будет равен hash(1, 10)
Т.е. получается не всегда при равенстве элементов определяемым методом __eq__ будет возвращаться одинаковый хэш? Или почему тогда это так работает?

fatesccgchannel
Автор

во первых спасибо за интересный урок! но вообще как я понял в python, hash функции работают не совсем классически?
т.к. по классике хеш функция нужна лишь для того что бы классифицировать обьект в хешь таблицу под нужным индексом для быстрого доступа или быстрого поиска. это ускоряет поиск до N(1). Но уже в хеш таблице должен хранится ключ не виде результата хеш функции, а именно данные получаемы при обращенни к имени переменной, тоесть в нашем случае это <__main__.Point object at и соответственно в словаре dict, должно получится два ключа соответствующих обьектам класса Point p1 и p2, которые должны находиться в одной ячейке хешь таблицы, но ключа всеже должно быть два. Былобы не плохо если бы Вы записали в будущем видио про устройство хешь функций именно для Python, или если оно у вас есть на канале, то прикрепили ссылку. Еще раз спасибо!

qjtkfwp
Автор

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

tenyjhb
Автор

Почему перестает работать алгоритм хеширования, когда мы переопределяем метод __eq__? Оператор сравнения где то используется в функции hash?

ProFart
Автор

если явно сравнить через is то получается это два разных объекта

zakirovio