objects as mutable dictionary keys
Steven Bethard
steven.bethard at gmail.com
Mon Dec 27 18:54:16 EST 2004
Peter Maas wrote:
> Steven Bethard schrieb:
>
>> 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.
>
> That's what I meant when I said that for lists id() doesn't make sense
> as hash because of the list literals.
As Andrew Koenig said, this has less to do with the fact that lists can
be written with list literals, and more to do with the fact that lists
are mutable containers. Because they're containers, it makes sense to
compare them by comparing their contents. But because they're mutable,
a hash value based on their contents cannot be guaranteed to be stable.
Hashing them by their id would force the user to mentally switch
between thinking of lists as containers and thinking of lists as
non-container objects.
Note that there is no such thing as a 'set literal', yet sets exhibit
the same behavior:
py> d = {set([1, 2]):100, set('a b'.split()):200}
Traceback (most recent call last):
File "<interactive input>", line 1, in ?
TypeError: set objects are unhashable
Sets are containers, and thus should be comparable by their contents.
But sets are mutable, so they cannot be hashed by their contents.
Rather than force the user to do the mental mind-switch between
container and non-container, Python opts to make sets unhashable.
Note that, much as tuples are to lists, frozensets are to sets:
py> d = {frozenset([1, 2]):100, frozenset('a b'.split()):200}
py> d[frozenset([2, 1])]
100
py> d[frozenset(['b', 'a'])]
200
Because frozensets are immutable, they can not only be compared by their
contents, but they can be hashed by these contents as well.
Steve
More information about the Python-list
mailing list