This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Title: reversed() requires a sequence - Could work on any iterator?
Type: Stage:
Components: Versions:
Status: closed Resolution: rejected
Dependencies: Superseder:
Assigned To: Nosy List: dstufft, madison.may, rhettinger, terry.reedy
Priority: normal Keywords:

Created on 2013-08-24 19:08 by dstufft, last changed 2022-04-11 14:57 by admin. This issue is now closed.

Messages (5)
msg196090 - (view) Author: Donald Stufft (dstufft) * (Python committer) Date: 2013-08-24 19:08
I noticed today that the builtin reversed() requires an explicit sequence and won't work with an iterator instead it throws a TypeError like:

>>> reversed(x for x in [1, 2, 3])
TypeError: argument to reversed() must be a sequence

It would be really great if reversed() worked on iterators too. Currently it requires an explicit list() before you can sent it back into reversed() which seems like it hurts readability.

For what it's worth I discovered this when trying to reverse the output of itertools.dropwhile.
msg196093 - (view) Author: Donald Stufft (dstufft) * (Python committer) Date: 2013-08-24 19:29
As an additional note this works how I would expect it to work if you're using sorted() instead of reversed() which I think is a stronger point in the favor of making reversed() work this way as well.

>>> sorted(x for x in [1, 2, 3])
[1, 2, 3]
msg196109 - (view) Author: Madison May (madison.may) * Date: 2013-08-25 01:53
Reversed doesn't make sense for all iterables.

>>> a = set([1, 2, 3])
>>> a = iter(a) # No error
>>> a = reversed(a) # Not typically desirable 

The point is that not all iterables are necessarily ordered.  And a reversed function shouldn't operate on unordered types.

Here's the relevant section of the docs for reversed():

    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).  

Your point about the sorted()'s behavior seems like a fair one, though. Perhaps it does make sense to support implicit conversion to lists for generator objects passed to reversed().
msg196573 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2013-08-30 20:52
The two cases are not parallel.
  a = sorted(b)
  a = list(b)
which occurred often enough to be a nuisance. With this proposal,
  a = reversed(b)
would abbreviate
  a = reversed(list(b))
which is probably less common and certainly less obnoxious than the two lines condensed by sorted.

A second problem: reversed already has a fallback default if (a presumably more efficient or effective) b.__reversed__ does not exit:

n = len(b)
a = [None]*n
for i,j in enumerate(range(n-1, -1, -1)): # reversed(range(n))
  a[i] = b[j]

(I believe this is more efficient, at least in C, than
  a = []
  for i in range(len(b)-1, -1, -1):
but it is hard to know.)

At what point, and under what conditions, would you introduce the second fallback?
msg196708 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2013-09-01 05:36
Sorry, Guido rejected this idea a long time ago.  We do have the __reversed__ hook so you can add reverse iteration to your own classes where it makes sense.

Doing it in the general case is more problematic.  Some data sources such as generators can't be run backwards so they would have to be run to exhaustion and saved in memory to support reversed iteration.  If a user wants this behavior, it is trivial to achieve it by running reversed(list(it)).  The user is in for unhappiness though if the underlying iterator is infinite or huge ;-)
Date User Action Args
2022-04-11 14:57:50adminsetgithub: 63026
2013-09-01 05:36:19rhettingersetstatus: open -> closed
resolution: rejected
messages: + msg196708
2013-08-30 20:52:25terry.reedysetnosy: + terry.reedy
messages: + msg196573
2013-08-25 01:53:05madison.maysetnosy: + madison.may
messages: + msg196109
2013-08-24 19:29:51dstufftsetmessages: + msg196093
2013-08-24 19:13:30pitrousetnosy: + rhettinger
2013-08-24 19:08:22dstufftcreate