TGTGInsighttelegram intelligenceLIVE / telegram public index
← Python Заметки

TGINSIGHT SIMILAR POSTS

Најди сличен содржај

Изворен канал @pythonotes · Post #370 · 19 јун.

Нередко требуется удалять дубликаты инстансов класса. Для этого обычно используется либо циклы со сравнением некоторых атрибутов, либо тип данных set(). При добавлении элемента в set происходит сравнение этого объекта по хешу. Если хеш совпадает с хешем уже существующего объекта, то происходит сравнение объектов на равенство. Если объекты равны, то новый объект не добавляется. class A: def __init__(self, pk: int): self.pk = pk def __repr__(self): return f"{self.__class__.__name__}(pk={self.pk})" set([A(pk=1), A(pk=2), A(pk=2)]) >>> {A(pk=1), A(pk=2), A(pk=2)} Далее для краткости метод `__repr__()` я буду пропускать По умолчанию в расчёте хеша, помимо прочего, используется адрес в памяти, который можно получить с помощью функции id(), поэтому все объекты считаются разными. Чтобы изменить способ сравнения объектов нам требуется переопределить метод __eq__() class A: def __init__(self, pk: int): self.pk = pk def __eq__(self, other): return self.pk == other.pk set([A(pk=1), A(pk=2), A(pk=2)]) >>> TypeError: unhashable type: 'A' Теперь в дело вступает логика, описаная в документации. Если вы переопределили __eq__() то следует переопределить и __hash__(). class A: def __init__(self, pk: int): self.pk = pk def __eq__(self, other): return self.pk == other.pk def __hash__(self): return hash(self.pk) set([A(pk=1), A(pk=2), A(pk=2)]) >>> {A(pk=1), A(pk=2)} Отлично, теперь всё работает. Этот же принцип действует и при наследовании. Допустим, вы создали дочерний класс class B(A): pass set([B(pk=1), B(pk=2), B(pk=2)]) >>> {B(pk=1), B(pk=2)} Теперь следует учитывать вот такое поведение hash(A(1)) == hash(B(1)) >>> True set([A(1), B(1)]) >>> {A(pk=1)} Инстансы А и В могут считаться идентичными, если они имеют одинаковые значения атрибутов и хеш, что может привести к неожиданным результатам при использовании множеств. Нужно учесть это в методах: class A: ... def __eq__(self, other): return isinstance(other, self.__class__) and self.pk == other.pk def __hash__(self): return hash((self.pk, self.__class__)) ... Но если вдруг решите как-то изменить способ сравнения в классе В... class B(A): def __eq__(self, other): return abs(self.pk) == abs(other.pk) set([B(pk=1), B(pk=2), B(pk=2)]) >>> TypeError: unhashable type: 'B' Снова получите ошибку. Та же логика - при переопределении метода __eq__() в новом классе метод __hash__() автоматически становится None и его тоже требуется переопределить. #tricks

Hashtags

Резултати

Пронајдени 1 слични објави

Пребарај: #tricks

当前筛选 #tricks清除筛选
sudo recast

@sudo_recast · Post #918 · 17.04.2025 г., 09:47

A useful command when you encounter conflicts while cherry-picking: tig HEAD $(git rev-parse CHERRY_PICK_HEAD 2>/dev/null) -- $(git diff --name-only --diff-filter=U | head -1) #tricks@sudo_recast

Hashtags