Why is dictionary.keys() a list and not a set?

  • Thread starter Christoph Zwerschke
  • Start date
?

=?ISO-8859-1?Q?=22Martin_v=2E_L=F6wis=22?=

Mike said:
Personally, I think we'd be better off to come up with a term for this
property that doesn't have a commonly understood meaning that has such
broad areas of disagreement with the property. I've been using
"hashable", which I would currently define as "has a __hash__ method
with the properties described in the __hash__ documentation, or does
not have either a __cmp__ or a __eq__ method."

I would like to use "hashable" as a term as well, but it appears that
many people would understand that to mean "has a __hash__
implementation" (i.e. hash(x) returns a value, instead of raising an
exception).

Regards,
Martin
 
C

Christoph Zwerschke

Martin said:
No. If you define both __hash__ and __eq__ consistently, then __hash__
would meet the specification. As posted in the example, __hash__ does
not meet the specification, contrary to Mike's claim that it does.

Ok, the example was incomplete, but in principle, this could be fixed by
adding a tweaked __eq__ method. So for completeness sake:

class mylist2(list):
def __hash__(self): return id(self)
def __eq__(self, other): return self is other
def __ne__(self, other): return self is not other

list = mylist2

a = list([1])
b = list([1])

print a, b, a == b, a != b
If you have a=[1] and b=[1], then *always* a==b; you cannot
change the semantics of list displays.

Surely, since you can't change the methods of built-in types. But you
can create your own local list displays with a tweaked semantics as in
the above example.

Anyway, the original question was: Are mylist1 and mylist2 (as above) to
be considered "hashable" types or not? I think "technically" speaking,
they are, and the "technical" definition is the only one that counts.

-- Christoph
 
?

=?ISO-8859-1?Q?=22Martin_v=2E_L=F6wis=22?=

Christoph said:
Anyway, the original question was: Are mylist1 and mylist2 (as above) to
be considered "hashable" types or not?

I long forgot was the original question was (I thought it was
"Why is dictionary.keys() a list and not a set?" :); anyway,
the answer to this question is certainly "yes".

Regards,
Martin
 
C

Christoph Zwerschke

Martin said:
I long forgot was the original question was (I thought it was
"Why is dictionary.keys() a list and not a set?" :)

Er, yes. Probably we should have opened a new thread instead:
"Improvement of the std lib doc concerning keys of sets/dicts".

-- Christoph
 
M

Mike Meyer

Martin v. Löwis said:
I would like to use "hashable" as a term as well, but it appears that
many people would understand that to mean "has a __hash__
implementation" (i.e. hash(x) returns a value, instead of raising an
exception).

Well, the two aren't quite the same thing: hash returns a value on
some things that don't have a __hash__. But that is close to the
meaning I want to give it. What meaning did you have in mind?

<mike
 
?

=?ISO-8859-1?Q?=22Martin_v=2E_L=F6wis=22?=

Mike said:
Well, the two aren't quite the same thing: hash returns a value on
some things that don't have a __hash__. But that is close to the
meaning I want to give it. What meaning did you have in mind?

Me, personally, I had your definition in mind: hashable should indicate
"returns a value constant over time and consistent with comparison".

I suggested that most people would consider "hashable" to mean:
hash() returns a value. To those people, it is a minor detail whether
you get the fallback implementation of hash() or whether there is a
default __hash__ implementation for all objects that don't otherwise
define __hash__.

Regards,
Martin
 
M

Mike Meyer

Martin v. Löwis said:
Me, personally, I had your definition in mind: hashable should indicate
"returns a value constant over time and consistent with comparison".

I suggested that most people would consider "hashable" to mean:
hash() returns a value. To those people, it is a minor detail whether
you get the fallback implementation of hash() or whether there is a
default __hash__ implementation for all objects that don't otherwise
define __hash__.

True. I think we ought to leave the behavioral requirements up to the
__hash__ docs, as it's already there. We can use hashable that way,
and maybe define it by implication:

Any object for which hash() returns an appropriate value(1) can be
used as a dictionary key/set element. Lists, sets and dicts are not
hashable, and can not be used. Tuples can be used if all the things
they contain are hashable. instances of all other builin types can be
used. Instances of most classes written in Python can be used(2).

1) See the __hash__ documentation for details on what an approriate
value is.

2) Instances that have a __hash__ method that returns an appropriate
value can be used. Instances that don't have a __cmp__ or an __eq__
method can be used even if they don't have a __hash__ method.

<mike
 
C

Christoph Zwerschke

Mike said:
Any object for which hash() returns an appropriate value(1) can be
used as a dictionary key/set element. Lists, sets and dicts are not
hashable, and can not be used. Tuples can be used if all the things
they contain are hashable. instances of all other builin types can be
used. Instances of most classes written in Python can be used(2).

1) See the __hash__ documentation for details on what an approriate
value is.

2) Instances that have a __hash__ method that returns an appropriate
value can be used. Instances that don't have a __cmp__ or an __eq__
method can be used even if they don't have a __hash__ method.

I think that is not so bad. How about this simplification:

Any hashable object(1) can be used as a dictionary key/set element.
Lists, sets and dicts are not hashable, and can not be used. Tuples can
be used if all the things they contain are hashable. Instances of all
other built-in types and most user-defined classes are hashable.

(1) Objects for which the hash() function returns an appropriate
(proper?) value. See the __hash__ documentation for details.

-- Christoph
 
M

Mike Meyer

Christoph Zwerschke said:
I think that is not so bad. How about this simplification:

Any hashable object(1) can be used as a dictionary key/set
element. Lists, sets and dicts are not hashable, and can not be
used. Tuples can be used if all the things they contain are
hashable. Instances of all other built-in types and most user-defined
classes are hashable.

(1) Objects for which the hash() function returns an appropriate
(proper?) value. See the __hash__ documentation for details.

I think that will do quite nicely, as the information about __hash__,
__cmp__ and __eq__ are all in the __hash__ documentation. You wrote it
- why don't you submit a PR with it?

<nmike
 
C

Christoph Zwerschke

Mike said:
I think that will do quite nicely, as the information about __hash__,
__cmp__ and __eq__ are all in the __hash__ documentation. You wrote it
- why don't you submit a PR with it?

Actually you wrote it ;-) Do suggestions like this one go to the normal
Python sf bug tracker?

-- Christoph
 
M

Mike Meyer

Christoph Zwerschke said:
Actually you wrote it ;-) Do suggestions like this one go to the
normal Python sf bug tracker?

Yup. I went ahead and did it. ID #1368768.

<mike
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,774
Messages
2,569,598
Members
45,158
Latest member
Vinay_Kumar Nevatia
Top