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 id
s, 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