I'm wondering what is the general way to define __hash__. I could add
up all the members. But I am wondering if this would cause a
performance issue for certain classes.
Regards,
Peng
#!/usr/bin/env python
class A:
def __init__(self, a, b) :
self._a = a
self._b = b
def __str__(self):
return 'A(%s, %s)' %(self._a, self._b)
__repr__ = __str__
def __cmp__(self, other):
if self._a < other._a:
return -1
elif self._a > other._a:
return 1
elif self._b < other._b:
return -1
elif self._b > other._b:
return 1
else:
return 0
def __hash__(self):
return self._a + self._b
if __name__ == '__main__':
x = A(1, 1)
aset = set()
aset.add(x)
print aset
What if A has a third member, which is a string? Is there a function
to convert an arbitrary string to an int?
Unless if you are very familiar with the math of hash functions, I don't
recommend that you try to implement one directly. Instead, make a tuple of the
hashable content of your class and return the result of calling hash() on that
tuple. Be sure to make your equality comparison do the right thing.
class A(object):
def __init__(self, a, b):
self.a = a
self.b = b
def _key(self):
# I include the name of the class so as to differentiate between other
# classes that might also have a _key() method. If you have several classes
# or subclasses that are allowed to compare equal to each other, use some
# other common string here.
return (type(self).__name__, a, b)
def __hash__(self):
return hash(self._key())
# Coincidentally, the _key() method can usually be reused for comparisons.
# I recommend doing this for the equality comparisons, at least, when you can
# because of the requirement that two items that compare equal must have the
# same hash value.
def __eq__(self, other):
return self._key() == other._key()
def __ne__(self, other):
return not (self == other)
...
--
Robert Kern
"I have come to believe that the whole world is an enigma, a harmless enigma
that is made terrible by our own mad attempt to interpret it as though it had
an underlying truth."
-- Umberto Eco
> def __hash__(self):
> return self._a + self._b
The hash of a tuple is based on the hash of its values. A common way to
define a hash method is:
def __hash__(self):
return hash((self._a, self._b))
Christian
Do I need to define other 4 comparison operators besides __eq__ and __ne__?
No; dictionaries are unordered and thus don't utilize the non-equality
comparison operators.
Cheers,
Chris
--
http://blog.rebertia.com
Yes. There are recipes to fill in the rest if you just provide __eq__ and __lt__:
http://code.activestate.com/recipes/576685/
Or you could continue to use the __cmp__ method, but it will be going away in
Python 3.
> def __cmp__(self, other):
> if self._a < other._a:
> return -1
> elif self._a > other._a:
> return 1
> elif self._b < other._b:
> return -1
> elif self._b > other._b:
> return 1
> else:
> return 0
This can be simplified to:
return cmp((self._a, self._b), (other._a, other._b))
--
Steven
Assuming you're not using Python 3.x that is.
If you're using Python 3, you won't be writing a __cmp__
method in the first place.
--
Greg