[Python-ideas] Fwd: Why do equality tests between OrderedDict keys/values views behave not as expected?

Random832 random832 at fastmail.com
Sat Dec 19 08:46:24 EST 2015


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)



More information about the Python-ideas mailing list