[IronPython] IronPython.Objects.List doesn't support GetHashCode()

Timothy Fitz firemoth at gmail.com
Thu May 12 15:13:12 CEST 2005

On 5/12/05, Chris Anderson <chrisan at gmail.com> wrote:
> Is there any special reason why this is the case? The code currently reads:
>        public override int GetHashCode() {
>            throw Ops.TypeError("list object is unhashable");
>        }
> So it's obviously intentional… however, I'm trying to use a native
> Python list as a data source for UI binding, and the collection needs
> to support GetHashCode? Is there any harm in implementing this method
> to just return the object identity hash?

Yes, there is harm in it. Try this in python hash([]) and you'll get
the same TypeError. The reason is because lists shouldn't be hashed.
List comparison is based on the items inside a list, not the instance
of the list itself. For instance:

from copy import deepcopy
A = [1,2]
B = deepcopy(A)
assert A == B
assert id(A) != id(B)

Now if we were to generate a hash value from the contents of the list,
which is how tuples work, this hash would become invalid if the list
were mutated, which would cause tremendous problems for dictionaries.
If we were to generate hash values from the id of a list, A and B,
which are equivelant, would be hashed to seperate locations. This
breaks the invariant that if A == B: d[A] = True; assert d[B].

In general, mutable objects should not provide hashing functions in python.

If only it were that simple,
The CLI library's arrays do provide GetHashCode. The difference here
is that python provides two functions, id and hash. Hash is
overridable by the class that you pass it, through the __hash__
member. id is provided by the implementation and guarantees simply
that it will return a unique identifier for every object. C# does not
have any analogue to id*, but instead provides GetHashCode for all

So the question is how do we resolve the difference? I'm not sure how
useful hashing lists is, but from pure python one should be able to do

class T(list):
  __hash__  = id

And this allows instances of T to be hashed, and instances of T are
exactly like lists.

In general when I need to do something like this, I use a subclass of
dictionary that hashes the id of all objects, not just lists.

Unfortunately I don't see a simple way to resolve this conflict when
you're forced to use someone elses hash table.

Timothy Fitz

* = Sortof, turns out Object.GetHashCode performs the same as id
although it's not guaranteed to and shouldn't be even remotely relied

More information about the Ironpython-users mailing list