Why is dictionary.keys() a list and not a set?
mwm at mired.org
Fri Nov 25 08:42:50 CET 2005
"bonono at gmail.com" <bonono at gmail.com> writes:
>> Not all tuples can be elements of a set. Elements of a set have to be
>> hashable. Tuples compute their hash by hashing their contents. If
>> their contents aren't hashable, the tuple isn't hashable, and hence
>> can't be an element of a set. If the values in the dictionary aren't
>> hashable, then the tuples returned by items() won't be hashable
>> either, and hence can't be elements of a set.
> A related issue, from the doc :
> Set elements are like dictionary keys; they need to define both
> __hash__ and __eq__ methods.
This is wrong. The objects must have a hash value to be used as a set
element or a dictionary key. Objects without a __hash__ use their id
as a hash value if they don't define their own comparisons. This makes
sense, because objects that don't define their own comparisons use id
testing for equality testing.
The __eq__ comment is even worse - __eq__ is unused on set elements or
dictionary keys. However, the *semantics* of sets and keys are such
that if hash(x) == hash(y), then x == y should also be true. If that's
false, then lots of the statements about dictionaries and sets are
going to be wrong.
The behavior of tuples is a different issue: hashing a non-hashable
object raises a TypeError. So does hashing a tuple that contains a
non-hashable object. This doesn't matter for most containers: lists
aren't hashable in any case; strings, unicode strings and xrange's, as
they contain only hashable objects. Buffers are poorly documented.
The dictionary doc comment is closer to right:
A dictionary's keys are almost arbitrary values. Only values
containing lists, dictionaries or other mutable types (that are
compared by value rather than by object identity) may not be used as
Proposed new wording, for both places:
A dictionaries keys (set element) can be any hashable value. Immutable
objects are hashable, except that a tuple containing a non-hashable
object isn't hashable. Mutable objects are hashable if they define
__hash__ or if they don't define comparison. A class or type that
defines both comparison and __hash__ should define them so that two
objects that have the same hash compare equal, otherwise using them as
dictionary keys (set elements) will not have the expected behavior.
What do the rest of you think?
Mike Meyer <mwm at mired.org> http://www.mired.org/home/mwm/
Independent WWW/Perforce/FreeBSD/Unix consultant, email for more information.
More information about the Python-list