"Steven D'Aprano" <[EMAIL PROTECTED]> wrote in message news:[EMAIL PROTECTED] |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.
The input specification strongly suggests that rev.next() successively yields seq[len(seq)-1], ..., seq[0] The main question is when len(seq) is called -- on creation as it is, or immediately before the first yield as you appear to expect, and as it would be in this generator (which does NOT match the actual implementation): def rev(seq): n = len(seq) while n: n =-1 yield seq[n] If len(seq) were called repeatedly (after the yield, for instance), then termination would no longer guaranteed (see below). I suppose the doc could be augmented with "The iterator is intialized once with len(sequence) when it is created, rather than when first used or anytime thereafter." But I wonder whether that would confuse those not thinking about corner case nuances. | and help(reversed) but neither gives any insight to what happens when you | use reversed() on a sequence, then modify the sequence. The sequence can potentially be modified between all calls to RL.next, and not just before the first as in your examples. abcs = list('abc') for a in reversed(abcs): print a abcs.append(a) The 'reverse' of a changing sequence, especially one changing in length, is a poorly defined concept. | >>> L = list("abc") | >>> RL = reversed(L) | >>> del L | >>> list(RL) | ['c', 'b', 'a'] | | This suggests that reversed() makes a copy of the list: Nope. 'del L' merely removes the association between 'L' and the list, leaving the internal association between RL and the list and hence the list itself. So the above is consistent with storing a reference (and an index initialized to len-1). | >>> L = list("abc") | >>> RL = reversed(L) | >>> L.append("d") | >>> list(RL) | ['c', 'b', 'a'] | | This suggests that reversed() uses a reference to the original list: It suggests that it uses a reference and an index initialized to len-1 when reversed is called (rather than when RL.next is first called). | >>> RL = reversed(L) | >>> L[0] = 'e' | >>> list(RL) | ['d', 'c', 'b', 'e'] | | And these examples suggests that reversed() is confused, or at least | confusing: This is completely consist with iterating down via reference and index. | >>> RL = reversed(L) | >>> del L[2] | >>> list(RL) | [] In the internal loop of list, RL first tries to return L[2]. But that raises an exception, so RL quits Terry Jan Reedy -- http://mail.python.org/mailman/listinfo/python-list