usual me
usual me

Reputation: 8778

Does reverse actually reverse a Python iterator?

So I can create a reverse iterator on a list:

list(reversed([0,1,2,3]))

[3, 2, 1, 0]

I assume this simply calls getitem from index len(...)-1 to 0. But then I cannot also do this:

list(reversed(xrange(4)))

[3, 2, 1, 0]

Now I am a bit confused. Does this create the list from xrange(4) and then reverse it? If not, how does it know what the last element is and how to go backwards? I read the documentation but it didn't help.

Upvotes: 6

Views: 1337

Answers (3)

Martijn Pieters
Martijn Pieters

Reputation: 1121654

reversed() looks for a __reversed__ special method on the object. List objects provide this, and so does xrange():

>>> xrange(4).__reversed__()
<rangeiterator object at 0x106e2fa50>

The iterator object simply produces the values in reverse, no list object is produced.

For objects that do not implement __reversed__, the reversed() function uses the length and the __getitem__ method; e.g. reversed() is essentially equivalent to:

def reversed(seq):
    try:
        return seq.__reversed__()
    except AttributeError:
        return (seq[i] for i in xrange(len(seq) - 1, -1 , -1))

where the second part is a generator expression, evaluating lazily. The generator then accesses each item in turn starting at index (length - 1) all the way down to index 0.

Upvotes: 9

user1907906
user1907906

Reputation:

Just compare the two:

In [2]: reversed(xrange(4))
Out[2]: <rangeiterator at 0x7fa83291bde0>

In [3]: list(reversed(xrange(4)))
Out[3]: [3, 2, 1, 0]

In [4]: reversed([0,1,2,3])
Out[4]: <listreverseiterator at 0x7fa8328be2d0>

In [5]: list(reversed([0,1,2,3]))
Out[5]: [3, 2, 1, 0]

Upvotes: 1

RemcoGerlich
RemcoGerlich

Reputation: 31260

reversed() can only take a sequence -- if it took generic iterators, it couldn't know what the final value was without exhausting the iterator and storing all the values.

Luckily, xrange returns an xrange object that works as a sequence:

>>> x = xrange(10)
>>> len(x)
10
>>> x[9]
9

It also happens to have an actual __reversed__ method, but that's a special case of having all the sequence methods.

Upvotes: 4

Related Questions