-1 on this new functionality 

Referring again to PEP 3106, and its support for views - this was inspired by the functionality seen with java.util.Map. Now that dict is sort of like java.util.LinkedHashMap - albeit safe for concurrent operations* - it's worth exploring if there's anything in the expanded API of LinkedHashMap vs Map that could inspire us for additions to Python.

I honestly don't see anything there. It is possible for LinkedHashMap to support cache behavior, through the use of removeEldestEntry (= potentially to pop on Python dict views, which then update the parent dict) and using access-based ordering (so more functionality than in Python currently), but in Java, this has been superseded in real usage by actually using specialized caches such as seen in Guava or Caffeine https://www.javadoc.io/doc/com.github.ben-manes.caffeine/caffeine/latest/index.html. (In turn, it's possible to use a Caffeine-based cache to support a lock-free version of LinkedHashMap - such caches are more general.)

We see the same thing in lru_cache in Python. Although it uses a dict as part of its implementation, this is further wrapped with a linked list (rather cleverly) to track access, whether in the pure Python implementation https://github.com/python/cpython/blob/master/Lib/functools.py#L479 or in the C equivalent. In general, such composite structures are exactly what the original poster would need. In that case, following the use case of working with database schema, it is just a matter of maintaining two indexes, one by name, the other by position.

We should keep the most heavily accessed object type in Python as lightweight as possible, and then build interesting structures around it, just like we always do.

*Due to the interaction of C code, Python code, and the GIL, dict in the CPython reference implementation can be treated as lock free, and this is how it is implemented in Jython with a ConcurrentHashMap.

- Jim

On Tue, Jul 7, 2020 at 11:13 AM Christopher Barker <pythonchb@gmail.com> wrote:
On Tue, Jul 7, 2020 at 6:56 AM Dominik Vilsmeier <dominik.vilsmeier@gmx.de> wrote:
Well, the point is that this "except comparisons" is not quite true:

     >>> i = {'a': []}.items()
     >>> s = {('a', 1)}
     >>> i == s
     TypeError: unhashable type: 'list'

If passed a set as `other` operand, dict_items seems to decide to
convert itself to a set, for no obvious reasons since, as you mentioned,
it does know how to compare itself to another view containing
non-hashable values:

     >>> i == {'a': {}}.items()

So if you're dealing with items views and want to compare them to a set
representing dict items, then you need an extra `try/except` in order to
handle non-hashable values in the items view. Not only does this require
an extra precautionary step, it also seems strange given that in Python
you can compare all sorts of objects without exceptions being raised. I
can't think of any another built-in type that would raise an exception
on equality `==` comparison. dict_items seems to make an exception to
that rule.

I think this really is a bug (well, missing feature). It surely, *could* be implemented to work, but maybe not efficiently or easily, so may well not be worth it -- is the use case of comparing a dict_items with another dict_items really helpful?

In fact, my first thought was that the way to do the comparison is to convert to a dict, rather than a set, and then do the compare. And then I realized that dict_items don't exist without a dict anyway, so you really should be comparing the "host" dicts anyway. Which leaves exactly no use cases for this operation.

I suppose we could add that capability by referencing the host dict if two dict_items are compared -- but really, why?

Though maybe a nicer message:

"TypeError: These views cannot be compared:  compare the dicts themselves"

 > An equality comparison between one `dict.values()` view and another
will always return `False`. This also applies when comparing
`dict.values()` to itself.

Surely that must be a relic from pre-3.7 days where dicts were unordered
and hence order-based comparison wouldn't be possible

well, maybe -- or it's not a relic, and rather a result of the fact that while dicts are now order-preserving, they are still order-not-important.

Given that:
In [90]: {'a' : 1, 'b' : 2} == {'b' : 2, 'a' : 1}                            
Out[90]: True

{'a' : 1, 'b' : 2}.values() == {'b' : 2, 'a' : 1}.values()

should also be True. but that's not possible to do correctly, since it can not be known that all the same values are there, there is no way to know that they are attached to the same keys. And if it did an order-preserving compare, then values would compare false when the dict is not the same.

So: we *could* either do an order preserving (by converting to a sequence) or not (by converting to a sequence and then sorting) comparison of the values -- but would that be at all useful? Do we ever need to ask the question:

Do these two dicts have all the same values without regard to the keys?

Now that I say that -- I suppose the answer is yes -- someone may want to ask that question -- but I think it would be better for them to ask it with their own code, so it's clear what it actually means.


Christopher Barker, PhD

Python Language Consulting
  - Teaching
  - Scientific Software Development
  - Desktop GUI and Web Development
  - wxPython, numpy, scipy, Cython
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-leave@python.org
Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/UAF4FUIUSTURSW665UDEMCAVQ7X7JDOM/
Code of Conduct: http://python.org/psf/codeofconduct/