P
PYTHON IN DEPTH🐍
@python_in_depth414 подп.
1.5Kпросмотров
19 мая 2023 г.
Score: 1.6K
Дублирование объектов в множестве Предположим, у нас есть сервер и его клиенты. Мы хотим отслеживать состояние клиентов на сервере и управлять ими. Для этой цели мы будем добавлять клиентов в коллекцию, чтобы избежать случайного дублирования одного и того же клиента на сервере. Давайте создадим класс 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 и более поздних версиях: 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, иначе это не будет работать 🦑 Если объекты идентичны, их хеши должны быть равными. 🦑 Хеш-функция должна содержать информацию, которая однозначно идентифицирует объект. 🦑 Хеш объекта не должен изменяться в течение его жизни (иначе могут возникнуть проблемы во время выполнения программы).
1.5K
просмотров
3685
символов
Да
эмодзи
Нет
медиа

Другие посты @python_in_depth

Все посты канала →
Дублирование объектов в множестве Предположим, у нас есть се — @python_in_depth | PostSniper