Repository navigation
MappingProxyType cannot hash a hashable underlying mapping #87995
Description
Activity
Objects of MappingProxyType do expose a __hash__() method, but if the underlying mapping is hashable, it still does not support hashing it.
Example:
Content of mp_hash.py:
------
#!/usr/bin/env pythonfrom nocasedict import NocaseDict, HashableMixin from types import MappingProxyType class HashableDict(HashableMixin, NocaseDict): """A hashable dictionary""" pass hd = HashableDict({'a': 1, 'b': 2}) print("hash(hd): {}".format(hash(hd))) mp = MappingProxyType(hd) print("hash(mp): {}".format(hash(mp)))
Running the mp_hash.py script:
hash(hd): 3709951335832776636 Traceback (most recent call last): File "/Users/maiera/Projects/Python/cpython/issues/mappingproxy/./mp_hash.py", line 14, in <module> print("hash(mp): {}".format(hash(mp))) TypeError: unhashable type: 'mappingproxy'
There are use cases where a function wants to return an immutable view on an internal dictionary, and the caller of the function should be able to use the returned object like a dictionary, except that it is read-only.
Note there is https://bugs.python.org/issue31209 on the inability to pickle MappingProxyType objects which was closed without adding the capability. That would fall under the same argument.
Reacted by Václav Brožík and Jan-Hein Bührman- added3.9 (EOL)end of lifeend of lifestdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directorytype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error
on Apr 13, 2021 Serhiy, what do you think? Would it make sense to pass through the underlying hash? I don't think there is much use for this but don't see any particular reason to block it.
Perhaps MappingProxyType is unhashable by accident. It implements __eq__, and it makes it unhashable by default. And nobody made request for this feature before. I think that implementing __hash__ would not make anything wrong.
But there is an issue with comparison implementation in MappingProxyType (see bpo-43838). Resolving that issue can affect the decision about hashability.
There should be always true the following predicate: if x == y then hash(x) == hash(y).
The issue #88004 (bpo-43838) was already closed with reasoning:
... the reason we proxy in the first place is not absolute safety but to make sure
people don’t accidentally update the dict when they intend to update the
class ...In general, it is hard to completely wall-off instances against deliberate efforts to pry them open
I do not se a reason why not allow the hashing. Recently I needed to collect a set of small unique dict objects. It is a pity that I could not utilize
MappingProxyTypedirectly.- added a commit that references this issue
on Jun 25, 2022 - added a commit that references this issue
on Jun 28, 2022 This is now fixed. Thanks, Serhiy! ✨ 🍰 ✨
Does this mean that this should no longer issue an "unhashable type" TypeError?
hash(MappingProxyType({3:2, 4:3}))Or is this feature indeed coming as of python 3.12?
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields: