Guido van Rossum writes:
The link between hashing and immutability is because objects whose hash would change are common, e.g. lists, and using them as dict keys would be very hard to debug for users most likely to make this mistake. The issue is that the dict implementation makes it impossible to find back keys whose hash has changed, other than by linear search, which is unacceptable -- but that's exactly what users will try to debug such issues, i.e., print the dict and notice that the missing key is indeed present.
Java doesn't seem to have this problem. Python uses dicts more heavily as part of its core architecture, sure, but those dicts use strings as their keys.
The consenting adults rule typically applies to things that are well hidden or marked (e.g. using __dunder__ names).
The ability to e.g. replace a class or module's functions, or values intended as constants, is not especially well-hidden.
There are plenty of things that Python could allow but doesn't, not because they are hard to implement or would violate an invariant of the interpreter, but because they could trip over naive users.
Note that you are turning things upside down: the question "why aren't all things hashable" came about because Andrew was considering making a hash table of the values of a dict.
Well, sure, but that's a reasonable way (if the ability to do so were present) to implement the operation being discussed under the performance constraints he specified.
But the real question here isn't "why aren't all things hashable" but "why can't you put mutable values into a set". The answer to the latter is because when we put a value into a container, and later the value changes, we can't tell the container, so if the container has any sort of lookup scheme other than linear search, it would lose track of the value.
Yes, but you're fine as long as the value doesn't change. What do you think about my __vhash__ idea? Someone would only make sets/dicts that use __vhash__ rather than __hash__ if they can guarantee the object won't change in the lifetime of its presence in the container (something that's no problem for the short-lived container that would be used for this operation)
Hashing comes into play because all of Python's common data structures use hashing to optimize lookup -- but if we used a different data structure, e.g. something based on sorting the keys, we'd still have the mutability problem. And we'd have worse problems, because values would have to be sortable, which is a stricter condition than being immutable.
In any case, you can't solve this problem by making all values hashable.
Sure I can. Normal dict values: def __eq__(self, b): return Counter(self) == Counter(b) #or e.g. Counter(map(self, make_vhash_key)) ... OrderedDict values: def __eq__(self, b): if isinstance(b, OrderedDict) return List(self) == List(b) else: return super().__eq__(b) # Yes, this isn't transitive, i.e. maybe: # a == c and b == c where a != b # but the same is true today for the dicts.
a = collections.OrderedDict(((1, 2), (3, 4))) b = collections.OrderedDict(((3, 4), (1, 2))) c = {1: 2, 3: 4} a == c, b == c, a == b (True, True, False)