Strange behaviour with reversed()

Gabriel Genellina gagsl-py2 at yahoo.com.ar
Thu Oct 18 07:49:12 CEST 2007


En Thu, 18 Oct 2007 01:31:13 -0300, Steven D'Aprano  
<steve at REMOVE-THIS-cybersource.com.au> escribió:

> I don't understand how reversed() is operating. I've read the description
> in the docs:
>
> reversed(seq)
> Return a reverse iterator. seq must be an object which supports the
> sequence protocol (the __len__() method and the __getitem__() method with
> integer arguments starting at 0). New in version 2.4.
>
> and help(reversed) but neither gives any insight to what happens when you
> use reversed() on a sequence, then modify the sequence.

A reversed object is rather simple: it stores the original sequence (a  
reference, as usual, not a copy!) and the next index to use, starting at  
len-1. Each time the next() method is called, the index is decremented  
until it goes below 0.
This is more or less the equivalent Python code:

class Reversed:
     def __init__(self, seq):
         n = len(seq)
         self.index = n-1
         self.seq = seq

     def __iter__(self):
         return self

     def next(self):
         index = self.index
         if index>=0:
             try: item = self.seq[index]
             except (IndexError,StopIteration): pass
             else:
                 self.index -= 1
                 return item
         self.index = -1
         self.seq = None
         raise StopIteration

Note that the starting index is determined at creation time, not when the  
iteration begins. So, if you create a reversed object over a list  
containing 3 elements, the first returned element will be seq[2], then  
seq[1], then seq[0]. It doesn't matter if you modify the list after  
creating the reversed object but before starting the iteration: it will  
start at seq[2] even if it's not the last item, and will silently stop if  
seq[2] is not a valid index anymore.

-- 
Gabriel Genellina




More information about the Python-list mailing list