# hashkey/digest for a complex object

Steven D'Aprano steve at REMOVE-THIS-cybersource.com.au
Sun Oct 10 16:28:42 CEST 2010

```On Sun, 10 Oct 2010 11:06:00 +0100, Arnaud Delobelle wrote:

> Steven D'Aprano <steve at REMOVE-THIS-cybersource.com.au> writes:
>
>> On Sat, 09 Oct 2010 21:39:51 +0100, Arnaud Delobelle wrote:
>>
>>> 1. hash() is an idempotent function, i.e. hash(hash(x)) == hash(x)
>>> hold for any hashable x (this is a simple consequence of the fact that
>>> hash(x) == x for any int x (by 'int' I mean 2.X int)).
>>
>> It's a beautiful theory, but, alas, it is not the case.
>>
>>>>> hash(-1) == -1
>> False
>>>>> hash(2**64) == 2**64
>> False
>>
>> to give only two of an infinite number of counter-examples.
>
> I can only see one counterexample, (-1).  2**64 is of type 'long' in 2.X
> on your machine (or, to be pedantic, 2.x where x >= 2).  And, in fact,
> (-1) is the only int such that hash(x) != x.

Fair point. I was mistaken.

I had the impression that the integration between ints and longs since
Python 2.2 was more extensive than it actually is. I made the above
comments based on the idea that since Python 2.2, longs are a subclass of
ints, e.g. that isinstance(2**64, int) would return True. Turns out that
I'm wrong, in which case I agree with you that -1 is the only int counter-
example.

As an aside, this makes me glad that I have continued writing
isinstance(x, (int, long)) in my code, even though I "knew" it was
unnecessary. Not the first time, and probably not the last, that a "this
can never happen" test saved the day.

--
Steven

```