This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: dict_values objects are hashable
Type: behavior Stage: needs patch
Components: Interpreter Core Versions: Python 3.4, Python 3.5, Python 2.7
process
Status: closed Resolution: rejected
Dependencies: Superseder:
Assigned To: rhettinger Nosy List: gvanrossum, rhettinger, roippi, serhiy.storchaka
Priority: low Keywords:

Created on 2014-08-13 20:52 by roippi, last changed 2022-04-11 14:58 by admin. This issue is now closed.

Messages (8)
msg225287 - (view) Author: Ben Roberts (roippi) * Date: 2014-08-13 20:52
In python 3.4 these result in a TypeError:

  hash({}.keys())

  hash({}.items())

But this succeeds:

  hash({}.values())

The 2.7 backports of these - viewkeys, viewitems, and viewvalues respectively - behave equivalently.

See more discussion on StackOverflow: http://stackoverflow.com/questions/25293912/why-are-some-dict-views-hashable

The cause appears to be that key and item views implement rich comparisons, whereas values views do not.  Therefore dict_view objects use the default id()-based __hash__ implementation.

Possible fix: explicitly set tp_hash to PyObject_HashNotImplemented for PyDictValues_Type - and perhaps for the other two view types as well, for symmetry.
msg225344 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2014-08-15 06:40
Do you want to submit a patch and tests?
Also take a look at the collections.abc MappingViews.
msg225347 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2014-08-15 09:37
There is a question. What builtin types should be hashable? In particular, should be hashable iterators, generators?
msg225353 - (view) Author: Ben Roberts (roippi) * Date: 2014-08-15 17:26
I have a patch with tests for this (running the test suite now) but I am increasingly unsure if python isn't doing the right thing already.

Intuitively, it "feels" wrong (to me) to allow a dict_values view to be hashable since the mapping onto which it provides a view is certainly mutable.  And mutable things shouldn't be hashable, everyone knows that.  However the dict_values object /itself/ doesn't violate the contract of hashability - its hash (which just uses its id()) doesn't change across its lifetime, and

   some_values_view == foo

will only be true iff

   foo is some_values_view

whereas e.g. some_keys_view == some_other_keys_view CAN change across the lifetime of those objects - so the asymmetry here does make sense.  It is taking me a while to wrap my brain around this because I often think in terms of "mutable/immutable" but the only thing that's important is the hashability contract, which is not currently violated by dict_values objects.

I'm certainly willing to be talked out of my change of opinion here :-), my intuition hasn't fully caught up with my logic.
msg225354 - (view) Author: Guido van Rossum (gvanrossum) * (Python committer) Date: 2014-08-15 17:34
It's clear that dict.values() shouldn't be hashable -- using the identity is plain wrong here. But shouldn't the fix be to implement rich comparisons for dict.values()?

I think just a a.keys() == set(a.keys()), a.values() should be == set(a.values()).

Let's move the question about whether generators and iterators should be hashable elsewhere.
msg225356 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2014-08-15 18:24
> I think just a a.keys() == set(a.keys()), a.values() should be ==
> set(a.values()).

Every element of a.keys() is hashable and unique. a.values() can contain non-
hashable repeated elements.
msg225358 - (view) Author: Guido van Rossum (gvanrossum) * (Python committer) Date: 2014-08-15 18:45
Oh. Yeah. Then I think there's nothing to do.
msg226450 - (view) Author: Ben Roberts (roippi) * Date: 2014-09-05 19:47
Going to close this down - implementing rich comparisons for values() does feel like the correct solution... but I don't think it's possible to implement __eq__ in better than nlogn time (and possibly space).

So nothing can realistically be done, yeah.
History
Date User Action Args
2022-04-11 14:58:06adminsetgithub: 66388
2014-09-05 19:47:11roippisetstatus: open -> closed
resolution: rejected
messages: + msg226450
2014-08-15 18:45:37gvanrossumsetmessages: + msg225358
2014-08-15 18:24:28serhiy.storchakasetmessages: + msg225356
2014-08-15 17:34:13gvanrossumsetmessages: + msg225354
2014-08-15 17:26:40roippisetmessages: + msg225353
2014-08-15 09:37:58serhiy.storchakasetmessages: + msg225347
2014-08-15 06:40:06rhettingersetpriority: normal -> low

nosy: + gvanrossum
messages: + msg225344

assignee: rhettinger
stage: needs patch
2014-08-14 05:40:18serhiy.storchakasetnosy: + serhiy.storchaka

versions: + Python 3.5
2014-08-14 01:08:08pitrousetnosy: + rhettinger
2014-08-13 20:52:43roippicreate