TGViewer
PYTHON IN DEPTH🐍 PYTHON IN DEPTH🐍 @python_in_depth · 386 subscribers
Post #42 1.51K
Дублирование объектов в множестве

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

Давайте создадим класс Client и добавим его в коллекцию (я также добавил метод repr для красивого вывода):

class Client:
def init(self, user_name):
self.user_name = user_name

def repr(self):
return self.user_name

fish1 = Client(user_name="catfish")

clients = set()
clients.add(fish1)

print(clients) # {catfish}

Замечательно, всё работает как задумано! Теперь попробуем добавить второго клиента и убедимся, что дублирования не происходит:

fish2 = Client(user_name="catfish")
clients.add(fish2)

print(clients) # {catfish}

Как это возможно? Мы добавили два абсолютно идентичных экземпляра в коллекцию, ожидая, что останется только один, но оба остались.

При добавлении объекта в коллекцию интерпретатор следует следующему правилу:

если a == b, то hash(a) == hash(b) должно быть обязательно выполнено.

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

Для сравнения объектов, коллекции и словари используют магический метод eq. Для пользовательских объектов этот метод определен по умолчанию. По умолчанию, два разных объекта не считаются равными, даже если они абсолютно идентичны:

print(fish1 == fish2) # False

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

🦑 В Python 2.6 и более ранних версиях hash(x) = id()
🦑 В Python 2.6 и более поздних версиях: (https://bugs.python.org/issue5169) hash(x) == id(x)/16

То есть, нельзя полагаться на то, что hash(x) = id().

Однако можно полагаться на то, что в Python у объектов по умолчанию есть хеш-значение, которое зависит от их идентификатора (id), и что хеш объекта не меняется в течение его жизни.

Так как в нашем примере объекты разные и занимают разные ячейки памяти, мы получаем:

print(hash(fish1), hash(fish2)) # 8786876890805 8786876904409

Так что можно сделать, чтобы объекты, которые мы считаем одинаковыми, объединялись в коллекции? Нужно переопределить методы hash и eq, чтобы явно указать интерпретатору, как сравнивать объекты и как рассчитывать хеш.

Для этого внесем изменения в определение класса:

class Client:
def init(self, user_name):
self.user_name = user_name

def repr(self):
return self.user_name

def hash(self):
return hash(self.user_name)

def eq(self, other):
if self.user_name == other.user_name:
return True
else:
return False

Теперь, при добавлении объектов в коллекцию, всё работает так, как ожидалось:

clients = set()

fish1 = Client(user_name="catfish")
clients.add(fish1)
fish2 = Client(user_name="catfish")
clients.add(fish2)

print(clients) # {catfish}

Помните, чтобы добавить объект вашего собственного класса в коллекцию или словарь в Python, вам необходимо:

🦑 Переопределить и метод hash, и метод eq, иначе это не будет работать (https://docs.python.org/3/reference/datamodel.html#object.__hash__)
🦑 Если объекты идентичны, их хеши должны быть равными.
🦑 Хеш-функция должна содержать информацию, которая однозначно идентифицирует объект.
🦑 Хеш объекта не должен изменяться в течение его жизни (иначе могут возникнуть проблемы во время выполнения программы).
  • 👍 5
  • ❤ 1
More from @python_in_depth
  1. Feb 20, 2026«Пузырь лопнул», «айти всё», «рынок умер» — каждый раз читаем это с новым интересом. Но да…
  2. Feb 18, 2026«Какой навык самый важный для разработчика?» Ответ неожиданно простой — умение учиться быс…
  3. Feb 9, 2026Как на самом деле работает отбор резюме в 2026 году Современный найм — это не «человек чит…
  4. Feb 2, 2026Ваш backend слишком сложный. Скорее всего — без причины. У большинства команд сложность ра…
  5. Jan 29, 2026Интеграции с внешними системами: как не превратить backend в зоопарк адаптеров Рано или по…
  6. Jan 29, 2025Еееееее, а че мы над js смеемся
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →