Strange behaviour with reversed()

Steven D'Aprano steve at REMOVE-THIS-cybersource.com.au
Thu Oct 18 04:52:27 EDT 2007


On Thu, 18 Oct 2007 15:24:27 +1000, Ben Finney wrote:

> Steven D'Aprano <steve at REMOVE-THIS-cybersource.com.au> writes:
> 
>> and help(reversed) but neither gives any insight to what happens when
>> you use reversed() on a sequence, then modify the sequence.
> 
> I would think the answer is the same for any question about modifying
> sequences while iterating: "undefined, therefore don't do that".

That's not correct. You can modify sequences while iterating, and the 
results are often perfectly predictable (but watch out for off-by-one 
errors):

>>> L = range(5)
>>> for item in L: # iterate over half of L
...     print item, "- deleting last item =", L[-1]
...     del L[-1]
...
0 - deleting last item = 4
1 - deleting last item = 3
2 - deleting last item = 2


(BTW, I'm not implying that the above is good practice. Far from it.)

The result of modifying sequences while you iterate over them is often -- 
not always -- hard to predict, but it is rarely indeterminate or 
undefined.

enumerate(), for example, iterates over the input sequence *as it is* at 
call time, not creation time. The result of modifying the sequence is 
well defined, but not necessarily what you want. For an exercise in 
Sorcerer's Apprentice, try this:

L = range(10)
for i, x in enumerate(L):
    print i, x
    L.append("another!")

Remember, ctrl-C to interrupt Python.


But even if it is undefined in the case of reversed(), there should be 
some sort of note in the docs. By analogy with sorted(), reversed() looks 
like it should make a copy. And if not, it looks like it should iterate 
over the input sequence as it exists when called. In fact, it does a 
little of both.


> In other words, if you think you'll be modifying the sequence during
> iteration (even if you're iterating indirectly via something like
> reversed()), iterate over a copy instead.

By analogy with sorted(), reversed() looks like it should be iterating 
over a copy. In any case, it isn't clear from the docs that reversed() is 
actually a type of view. I like views, it's just that I like to know when 
I'm working with one.


-- 
Steven.



More information about the Python-list mailing list