How to filter objects in list in python?

Viewed 233

I am using python 3.6. to create two lists. I want to filter it if all of the instances attribute values are the same.

I wrote this code, but it returns false. How to filter it?

class MyCls:
    def __init__(self, **kwargs):
        self.x = kwargs.get('x')
        self.y = kwargs.get('y')
        self.z = kwargs.get('z')

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

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

    def __eq__(self, other):
        return str(self.__hash__) == str(other.__hash__)


a = MyCls(x='a', y='b', z='c')
b = MyCls(x='a', y='b', z='c')

ab = [a, b]

print(a is b)
# False
print(a == b)
# False

s = set(ab)
print(s)
# print(2 instances)
1 Answers

I'm answering on the premise that you are playing around with __hash__ and __eq__ for educational purposes.

I find your hashing and equality methods... weird.

Anyway, the concrete problem with your code is that __eq__ does not call the __hash__ method.

You can use

return str(self.__hash__()) == str(other.__hash__())

in __eq__ - or better (but still weird)

return hash(self) == hash(other)

With this adjustment you get

>>> hash(a)
>>> 8280333490847949293
>>> hash(b)
>>> 8280333490847949293
>>> a == b
>>> True

However, a fundamental flaw with this design is that an instance of MyClass will compare equal with any other object that hashes the same by accident.

>>> class C:
...:    def __hash__(self):
...:        return 8280333490847949293
...:    
>>> C() == a
>>> True

If you want to compare instance attributes, why not compare the instance dicts directly?

Related