Веб-версияОткрыть в Telegram

ВеткаДублирование объектов в множестве

3 сообщения · –
P
Дублирование объектов в множестве Предположим, у нас есть сервер и его клиенты. Мы хотим отслеживать состояние клиентов на сервере и управлять ими. Для этой цели мы будем добавлять клиентов в коллекцию, чтобы избежать случайного дублирования одного и того же клиента на сервере. Давайте создадим класс 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__) 🦑 Если объекты идентичны, их хеши должны быть равными. 🦑 Хеш-функция должна содержать информацию, которая однозначно идентифицирует объект. 🦑 Хеш объекта не должен изменяться в течение его жизни (иначе могут возникнуть проблемы во время выполнения программы).
2 · 1.5K ·
  1. А
    Хей, парни.Я новичок в пайтон разработке. Хотел бы вместе с такими же, организовать командную разработку чего-либо для опыта в области командной разработки, GIT, GIT HUB Если интересно - пиши в личку
  2. S
    Всем привет! У меня есть канал про становление программистом, подписывайтесь, кому интересно) @python_in_my_heart
🐍🐍Python🪆🐍Python🪆@python_chat_ru · группа · Технологии
20участников39сообщений в индексе
Лента площадки Открыть в Telegram

Открытая публичная лента из поискового индекса ChatCrawler — «Google по публичному Telegram»; обновляется по мере обхода площадки. Время — UTC.

Только публичный контент, официальный API Telegram. О проекте · Вопросы · Чего мы не делаем · Убрать страницу из выдачи · Каталог · Поиск · Как мы считаем