What is the Python equivalent of Comparables in Java?

Instead of using instances of Category (e.g. Category('Analyze', 'True', 'False', 'False', 'FINAL')) as the keys in your dictionary, it sounds like you should be using the associated tuple (e.g. ('Analyze', 'True', 'False', 'False', 'FINAL')).

If you really do want to use instance of Category as the keys in the dictionary, you'll need to define both the __hash__ and __eq__ methods. For example:

class Category(object):
    def __init__(self,*args):
        self.args=args
    def __hash__(self):
        # Note that this assumes that Category's hash value is immutable
        # i.e. self.args does not change.
        return hash(self.args)
    def __eq__(self,other):
        return self.args == other.args

a=Category('Analyze', 'True', 'False', 'False', 'FINAL')
b=Category('Analyze', 'True', 'False', 'False', 'FINAL')

mydict={a:1}

a and b are distinct instances, so they have different ids, but their hash values are the same:

assert id(a) != id(b)
assert hash(a)==hash(b)

This shows b is an acceptable key in mydict:

print(mydict[a])
# 1
print(mydict[b])
# 1

PS. Don't bother with __cmp__. In Python 3:

The cmp() function should be treated as gone, and the __cmp__() special method is no longer supported. Use __lt__() for sorting, __eq__() with __hash__(), and other rich comparisons as needed.


As you can apparently put your category instances into a dict, you must have overwritten __hash__ already. All you need now is __eq__:

class Category(object):
    # you must have overwritten `__hash__` like this already
    def __hash__(self):
        return hash((self.attr1, self.attr2, ... ))

    # now you just need tis
    def __eq__(self, other):
        return isinstance(other, Category) and \
               (self.attr1, self.attr2, ... ) == (other.attr1, other.attr2, ... )

What you should really do is throw that whole class away and use a collections.namedtuple instead:

Category = collections.namedtuple('Category', 'attr1 attr2 attr3')

First: use True and False (boolean properties) instead of 'True' and 'False' (string properties).

Generally, you can make everything comparable in Python. You just have to define specific methods (like __eq__, __lt__, etc.) for your class.

So, let's say I want to compare instances of class A, and the comparison should be just case-insensitive string comparison of s member:

class A(object):
    def __init__(self, s=''):
        self.s = s

    def __eq__(self, other):
        return self.s.lower() == other.s.lower()

a = A('aaaa')
b = A('AAAA')
print a == b # prints True
b = A('bbbb')
print a == b # prints False

Tags:

Python