On Mon, Jun 29, 2020 at 11:02:54PM -0700, Christopher Barker wrote:
> Or is it a set because it can’t be indexed? If I have the history right,
> dict.items was first implemented with the “old” dict implementation, which
> did not preserve order, but did provide O(1) access, so making the dict
> views set-like was easy, and making them Sequences was impossible.
No, making them set-like was intentional.
The history goes something like this:
In Python 1, and early Python 2, dict.keys(), .values() and .items()
each returned lists. Some time by 2.4 (possibly earlier) dicts grew
additional methods returning iterators:
dict.iterkeys() .itervalues() .iteritems()
As part of the migration from Python 2 to 3, it was planned to change
them to set-like views:
so as an aid to migration, these set-like views were added to 2.7:
dict.viewkeys() .viewvalues() .viewitems()
and finally in 3.x, the list and iterator versions were all dropped and
the views were renamed.
So there was already a sequence version of items etc, and the set-like
views were explicitly intended to be set-like.
Thanks for the details, but I just re-read the PEP, and I'm not sure my hand wavy version is wrong:
> there was already a sequence version of items etc
Well, yes, but they explicitly created list copies -- there was no sequence-like version that was a view.
The first improvement on that was the iter* methods, and then (inspired by JAVA) it was determined that we could have view objects that could provide efficient iterators, and also set-like behavior. But I don't see any comments in the PEP about why indexing was rejected, but it's implicit in the fact that dicts were explicitly unordered at the time that PEP was written.
Now that dicts do preserve order, and there is an implementation that can provide somewhat efficient indexing ( not O(1), but yes O(N) with a small constant) there is the opportunity to add a new feature.
It does bring up a question: if the view objects support indexing, it would be a bit odd for two dict view objects to be equal if they have the same elements, but not the same order, but that would be required to remain consistent with the way dicts currently are (and will remain) One way to think about is that adding indexing to the views would NOT make them Sequences, it would simply provide that one feature.
So how useful is that feature? I recall a couple (actually, essentailly one) which is selecting an arbitrary or random item from a dict, i.e. being able to pass a dict view to random.choice()
As it happens. I've had that use case, but if that's the only one folks can think of, then maybe not particularly worthwhile.
Final note about performance: yes, we don't want to encourage folks to use not-great-performance approaches, but the alternative to the O(N) with small constant performance being proposed here is to make a Sequence out of the views, and then index into them, which is O(N) with a larger constant and more memory use.