Why are python dictionaries not reversible for python3.7?

From the docs:

reversed(seq)

Return a reverse iterator. seq must be an object which has a __reversed__() method or supports the sequence protocol (the __len__() method and the __getitem__() method with integer arguments starting at 0).

A dict object doesn't implement __reversed__. It does implement both of the latter methods. However, __getitem__ takes keys as arguments, rather than integers (starting at 0).

As to why, this has already been suggested and discussed here.

EDIT:

These quotes are from Python-Dev mailing list (thread "Add __reversed__ methods for dict", started on 25. 05. 18), I'll start with the "conceptual" arguments, first one is from Antoine Pitrou:

It's worth nothing that OrderedDict already supports reversed(). The argument could go both ways:

  1. dict is similar to OrderedDict nowadays, so it should support reversed() too;

  2. you can use OrderedDict to signal explicitly that you care about ordering; no need to add anything to dict.

My thought is that guaranteed insertion order for regular dicts is brand new, so it will take a while for the notion settle in and become part of everyday thinking about dicts. Once that happens, it is probably inevitable that use cases will emerge and that __reversed__ will get added at some point. The implementation seems straightforward and it isn't much of a conceptual leap to expect that a finite ordered collection would be reversible.

Followed by Raymond Hettinger's reply:

Given that dicts now track insertion order, it seems reasonable to want to know the most recent insertions (i.e. looping over the most recently added tasks in a task dict). Other possible use cases will likely correspond to how we use the Unix tail command.

If those use cases arise, it would be nice for __reversed__ to already be supported so that people won't be tempted to implement an ugly workaround using popitem() calls followed by reinsertions.

The main concern expressed in the mailing list was that this would add too much bloat or reduce memory efficiency (having to have doubly linked lists instead of singly linked ones) in at least some implementations, here's Inada Naoki's quote from Python bug tracker (issue 33462):

"Have an order" doesn't mean "reversible". For example, single linked list is ordered, but not reversible.

While CPython implementation can provide efficient __reverse__, adding __reverse__ means all Python implementation is expected to provide it. For example, some Python implementation may be able to implement dict with hashmap + single linked list. If __reverse__ is added, it's not possible anymore.

Back to the mailing list, here are the two last messages (both posted on 08.06.2018). First is from Michael Selik:

Am I correct in saying that the consensus is +1 for inclusion in v3.8?

The last point in the thread was INADA Naoki researching various implementations and deciding that it's OK to include this feature in 3.8. As I understand it, Guido was in agreement with INADA's advice to wait for MicroPython's implementation of v3.7. Since INADA has changed minds, I'm guessing it's all in favor?

Concluding with Guido van Rossum's message:

That sounds right to me. We will then have had two versions where this was the case:

  • 3.6 where order preserving was implemented in CPython but in the language spec

  • 3.7 where it was also added to the language spec

As noted in the other answer and comments, reversed() is supported for both dicts and dictviews since version 3.8 (14.10.2018).


Since python 3.8 reverse() is useable on dicts

Dict and dictviews are now iterable in reversed insertion order using reversed(). ( Contributed by Rémi Lapeyre in bpo-33462.)


Update for python 3.8

Dict and dictviews are now iterable in reversed insertion order using reversed()

>>> dict = {1: "1", 2: "2", 3: "3"}
>>> reversed(dict)
<dict_reversekeyiterator object at 0x7f72ca795130>