Почему наборы допускают создание нескольких одинаковых объектов с изменением hashCodes? - PullRequest
1 голос
/ 07 октября 2019

Согласно моему пониманию, в наборах может быть только один предмет. Но я нашел следующий пример, где набор имеет два одинаковых объекта

class myObject:

    def __init__(self, x):
        self.x = x

    def set(self, x):
        self.x = x

    def __hash__(self):
        return self.x

    def __eq__(self, o):
        return self.x == o.x

    def __str__(self):
        return str(self.x)

    def __repr__(self):
        return str(self.x)

Когда я запускаю следующее:

x = myObject(1)

mySet = {x}

x.set(2)
mySet.add(x)

print(mySet)

x.set(3)

print(mySet)

Я получаю следующий вывод:

{2, 2}
{3, 3}

Если я удаляю методы __str__ и __repr__, это показывает, что в наборе есть два объекта с одинаковым адресом памяти:

{<__main__.myObject object at 0x10e3a10d0>, <__main__.myObject object at 0x10e3a10d0>}

Я знаю, что Python не разрешает вещиПодобные списки должны быть хешированы, потому что хеш-код может измениться, вызывая ошибку, аналогичную показанной выше. Почему python разрешает это, но не для таких вещей, как списки и т. Д. Конечно, Python должен также иметь какой-то способ управления изменением хешей.

Я протестировал этот же пример на Java, и происходит то же самое. Почему эти языки позволяют это?

1 Ответ

2 голосов
/ 07 октября 2019

имеет здесь ссылку на документацию, в которой указан хеш

Что такое хеш: https://docs.python.org/3/reference/datamodel.html#object.hash

Что такое хешируемый (ВАЖНО) : https://docs.python.org/3/glossary.html#term-hashable

"Объект является хешируемым, если он имеет хеш-значение , которое никогда не изменяется в течение срока его службы ... "

Просмотр самого заданного объекта после того, как вы изменили x.

s = set()
x = myObject(2)

Затем посмотрите на хэш члена набора:

enter image description here

Тогда:

x.set(4)

enter image description here

Без изменений. Фактически, если вы продолжите использовать этот набор в других местах (например, fs = frozenset (s)), вы продолжите передавать старый хеш.

...