On Thu, May 19, 2011 at 10:43 PM, Ethan Furman <et...@stoneleaf.us> wrote: > Several folk have said that objects that compare equal must hash equal, and > the docs also state this > http://docs.python.org/dev/reference/datamodel.html#object.__hash__ > > I'm hoping somebody can tell me what horrible thing will happen if this > isn't the case? Here's a toy example of a class I'm thinking of writing > that will compare equal with int's, but hash differently: > > --> class Wierd(): > ... def __init__(self, value): > ... self.value = value > ... def __eq__(self, other): > ... return self.value == other > ... def __hash__(self): > ... return hash((self.value + 13) ** 3) > ... > --> one = Wierd(1) > --> two = Wierd(2) > --> three = Wierd(3) > --> one > <Wierd object at 0x00BFE710> > --> one == 1 > True > --> one == 2 > False > --> two == 2 > True > --> three == 3 > True > --> d = dict() > --> d[one] = '1' > --> d[two] = '2' > --> d[three] = '3' > --> d > {<Wierd object at 0x00BFE710>: '1', > <Wierd object at 0x00BFE870>: '3', > <Wierd object at 0x00BFE830>: '2'} > --> d[1] = '1.0' > --> d[2] = '2.0' > --> d[3] = '3.0'
This is the part considered "horrible": > --> d > {<Wierd object at 0x00BFE870>: '3', > 1: '1.0', > 2: '2.0', > 3: '3.0', > <Wierd object at 0x00BFE830>: '2', > <Wierd object at 0x00BFE710>: '1'} Compare: >>> x = {5.0 : 'foo'} >>> x[5] 'foo' Here's a more common/plausible "horrible" case closer to what the docs writers had in mind: >>> class Naughty(object): ... def __init__(self, n): ... self.n = n ... def __eq__(self, other): ... return self.n == other.n ... >>> Naughty(5) == Naughty(5) True >>> Naughty(5) is Naughty(5) False >>> bad = Naughty(3) >>> y = {bad : 'foo'} >>> y[bad] # just happens to work 'foo' >>> del bad >>> # ok, how do we get to 'foo' now? >>> y[Naughty(3)] # try the obvious way Traceback (most recent call last): File "<stdin>", line 1, in <module> KeyError: <__main__.Naughty object at 0x2a1cb0> >>> # We're screwed. Naughty instances (and similar) can't be used sensibly as hash keys (unless you /only/ care about object identity; this is often not the case). Cheers, Chris -- http://rebertia.com -- http://mail.python.org/mailman/listinfo/python-list