???? i can`t understand it

Alex Martelli aleax at aleax.it
Fri Aug 8 08:49:41 EDT 2003


Sean 'Shaleh' Perry wrote:
   ...
> I read this as "do not remove items from a list you are iterating over".
> Pretty sure the docs comment on this as well.

Right!  More generally, don't ALTER a list you are iterating over --
additions are just as deleterious as removals (indeed, potentially
worse, as an endless loop may result).  If you want to alter a list,
you may iterate over a COPY of that list, e.g.:

for item in list(mylist):
    if iswonderful(item):
        mylist.append(item)    # better have 2 copies of this item

but in some cases even that solution is inferior.  For example,
consider the task "remove all multiples of 3 from my list".

# Naive implementation of this idea:

def remove3s(mylist):
    for item in list(mylist):
        if item%3 == 0: mylist.remove(item)

# let's see how long it takes...

import timeit

timeit.remove3s = remove3s
t = timeit.Timer('x=666*[33]+666*[22]; remove3s(x)')
print 'remove3s:', min(t.repeat(3,100))

# perhaps a better idea...:
def cleano3s(mylist):
    clean = [item for item in mylist if item%3]
    mylist[:] = clean

# and how about its timing, then?
timeit.cleano3s = cleano3s
t = timeit.Timer('x=666*[33]+666*[22]; cleano3s(x)')
print 'cleano3s:', min(t.repeat(3,100))


On my machine, this gives:

remove3s: 0.759788990021
cleano3s: 0.178290963173

i.e., the 'clean' idea (build a new "cleaned-up" list with a list
comprehension then substitute it in-place in the original list)
is over 4 times faster than the 'remove' idea for this case... the
'remove' method of a list in general is O(N) [whenre N is the
length of the list), so a loop of O(N) removes is going to be
O(N squared), while a list comprehension is O(N).  For large enough
lists, these differences do matter.


Alex





More information about the Python-list mailing list