objects as mutable dictionary keys

Steven Bethard steven.bethard at gmail.com
Mon Dec 27 23:12:52 CET 2004

Peter Maas wrote:
> This strikes me because if one can do this with instances of user
> defined classes why not with lists? Trying to use lists as dict
> keys yields "TypeError: list objects are unhashable". So why are
> list objects unhashable and user defined objects hashable? For
> user defined objects hash(x1) = id(x1), why not do the same
> with lists?
> I think it's because of the existence of list literals. If you
> would use id() as a hash function for lists how should d[[1,2,3]]
> be stored? For instances of user defined classes there is no
> literal and accordingly no problem to use id() as a hash function
> and instances as dictionary keys.
> Is that correct?

Well, there's no problem getting an id of a list without a name if 
that's what you mean:

py> lst = [[1,2,3]]
py> id(lst[0])

If lists were hashable, new programmers to Python would almost certainly 
make mistakes like:

py> d = {[1, 2, 3]: 'abc'}

The coder here almost certainly *doesn't* want that list to be compared 
by id.  The only way to get a binding for that list would be using the 
dict's keys or __iter__ methods.

The coder here almost certainly wants to compare by value so that the 
following code works:

py> d[[1, 2, 3]]

Of course, this is what tuples are for -- Python even supports special 
syntax for using them this way:

py> d[1, 2, 3]

So my suspicion is that lists are not hashable because it prevents what 
would be a very easy mistake to make.  Yes, it means you can't use your 
lists as keys to a dict, but how often do you want to do that anyway?  I 
don't think I've ever wanted to do that.  If I ever do, I'll probably 
just do something like:

py> lst1, lst2 = [1, 2, 3], 'a b c'.split()
py> d = {id(lst1):100, id(lst2):200}
py> d[id(lst1)]
py> d[id(lst2)]

Certainly I don't mind having to be explicit for an unusual case if it 
saves me a little trouble for the more common cases.


More information about the Python-list mailing list