Most efficient solution?

Alex Martelli aleaxit at
Mon Jul 16 16:55:12 EDT 2001

"Jay Parlar" <jparlar at> writes:
> > > for eachItem in A:
> > >     if eachItem in B:
> > >         A.remove(eachItem)
> > >
> > > Now, this will work fine,
> >
> > Are you sure about that?  Normally, modifying the list
> > you're iterating on does NOT work fine.  Have you tested
> Hmm... That's very interesting. Well, I guess you learn something new
every day ;-) I suppose the simple solution (to my
> original code) is to place all non-offending items in a new list, ie.
> >>> for eachItem in a:
> ... if each not in b:
> ... final.append(eachItem)
> ...

Or, more simply, loop on a _copy_ of the list you need to alter:
    for eachItem in a[:]:
        if eachItem not in b: a.remove(eachItem)

> I've never noticed the list behaviour before that you pointed out, what
causes that, if you don't mind my asking?

Officially, the point is that altering the list you're iterating on causes
unspecified behavior -- whatever happens to happen, happens:-).
In practice, the loop on the list has more or less these semantics:

    i = 0
    while 1:
        try: item = a[i]
        except IndexError: break
        else: i += 1

being equivalent to:

    for item in a:

If you alter a, the index i used internally still goes up by one each
time through the loop, until it hits an IndexError (which tells the
interpreter that the for-loop is finished).  So, say the loop's body
is just a.remove(item).  Now:
    for item in a: a.remove(item)
we can see as equivalent (in the current implementation) to:
    i = 0
    while i<len(a):
        a[i:i+1] = []
        i = i+1
which deletes *alternate* items of list a...

...but you shouldn't rely on this to do "clever" things -- tomorrow,
the for loop implementation might be optimized and do OTHER
strange things when the body alters the list it's looping on!-)


Do You Yahoo!?
Get your free address at

More information about the Python-list mailing list