-2
class MyObject(object):

    def __init__(self, no, text):
        self.no = no
        self.text = text

    def __eq__(self, other):
        if isinstance(other, self.__class__):
            return self.text == other.text
        return False

    def __hash__(self):
        return hash(str(self))

my_list = {MyObject(1, 'a'), MyObject(2, 'a'), MyObject(0, 'b')}


print(my_list)

This still prints out 3 objects, but I want to remove one of the elements which has the same 'a'. Why doesn't it work? I defined the MyObject class for this de-duplication purpose.

marlon
  • 6,029
  • 8
  • 42
  • 76
  • 4
    What do you expect `str(self)` in `hash(str(self))` to be? Surely you meant `hash(self.text)` – Paul M. Jul 22 '22 at 23:21
  • 1
    That's not a `list` [btw](https://stackoverflow.com/questions/2831212/python-sets-vs-lists) – 0x263A Jul 22 '22 at 23:22
  • Also, although I don’t know what you’re using it for, you should be careful of defining objects to be equal for set-making convenience when they’re not really logically equal. A dict of `{obj.text: obj}` can accomplish the same deduplicating effect more explicitly. – Ry- Jul 22 '22 at 23:24
  • @Ry- I tend to disagree. Whether 2 objects are equal is completely context\domain dependant. In most contexts I'd totally expect `obj1 == obj2` and `{obj1, obj2} == {obj1}` to be true at the same time but I assume this is totally a philosophical discussion – DeepSpace Jul 22 '22 at 23:27

2 Answers2

1

You have to either change the hash method's return value to hash(self.text), or, you can keep its return as hash(str(self)) and add a __str__ method whose return value is self.text.

DjaouadNM
  • 22,013
  • 4
  • 33
  • 55
0

You didn’t define a __str__ or a __repr__, and the default repr includes the object’s id.

Ry-
  • 218,210
  • 55
  • 464
  • 476