If there's a list like below

s=['b','a','r','r','i','s','t','e','r']

and if I tried to remove every 'r' from the list like this

>>> for x in s:
    if(x=='r'):
        s.remove(x)

it gives the following result.

>>> s
['b', 'a', 'i', 's', 't', 'e', 'r']

Why isn't the last 'r' removed from the list.

'r' was encountered only twice, add a few prints to see what happens

s = ['b','a','r','r','i','s','t','e','r']
for x in s:
    print x,
    if(x == 'r'):
        print "\n", s, "-->",
        s.remove(x)
        print s

print "Second version: "
s = ['b','a','r','r','i','s','t','e','r']
for x in list(s):
    print x,
    if(x == 'r'):
        print "\n", s, "-->",
        s.remove(x)
        print s

""" my output-->
b a r 
['b', 'a', 'r', 'r', 'i', 's', 't', 'e', 'r'] --> ['b', 'a', 'r', 'i', 's', 't', 'e', 'r']
i s t e r 
['b', 'a', 'r', 'i', 's', 't', 'e', 'r'] --> ['b', 'a', 'i', 's', 't', 'e', 'r']
Second version: 
b a r 
['b', 'a', 'r', 'r', 'i', 's', 't', 'e', 'r'] --> ['b', 'a', 'r', 'i', 's', 't', 'e', 'r']
r 
['b', 'a', 'r', 'i', 's', 't', 'e', 'r'] --> ['b', 'a', 'i', 's', 't', 'e', 'r']
i s t e r 
['b', 'a', 'i', 's', 't', 'e', 'r'] --> ['b', 'a', 'i', 's', 't', 'e']
"""

Conclusion: don't modify the size of a list while iterating on this list, use a copy if necessary. Also the standard way to do it is

s = ['b','a','r','r','i','s','t','e','r']
s[:] = (x for x in s if x != 'r')

Edited 4 Years Ago by Gribouillis: n/a

Conclusion: don't modify the size of a list while iterating on this list, use a copy if necessary.

yes using a copy solves the problem thank you but I have couple of questions about the second method.
If I understood correctly

s[:] = (x for x in s if x != 'r')

means reconstruct the list s from the components of the list s itself (interating through them ) but skip the element 'r' right?
Also why can't we use just s instead of s[:].

s=(x for x in s if x!= 'r')
>>> s
<generator object <genexpr> at 0xa80ff54>

yes using a copy solves the problem thank you but I have couple of questions about the second method.
If I understood correctly

s[:] = (x for x in s if x != 'r')

means reconstruct the list s from the components of the list s itself (interating through them ) but skip the element 'r' right?
Also why can't we use just s instead of s[:].

s=(x for x in s if x!= 'r')
>>> s
<generator object <genexpr> at 0xa80ff54>

If you want to use s, write

s = [x for x in s if x!= 'r']
# or
s = list(x for x in s if x!= 'r')

there is a small difference with s[:] because this code create a new list for the name s. With s[:] it only fills the same list object with new elements. For example try this

a = ['b','a','r','r','i','s','t','e','r']
b = a
c = a
b = [x for x in b if x != 'r']
print a
c[:] = [x for x in c if x != 'r']
print a

print id(a), id(b), id(c)

If you want to learn more about generator expressions, read about generators and the iterator protocol in the python documentation, but you can postpone this a little if you are new to python.

Edited 4 Years Ago by Gribouillis: n/a

If you want to use s, write

s = [x for x in s if x!= 'r']
# or
s = list(x for x in s if x!= 'r')

there is a small difference with s[:] because this code create a new list for the name s. With s[:] it only fills the same list object with new elements. For example try this

a = ['b','a','r','r','i','s','t','e','r']
b = a
c = a
b = [x for x in b if x != 'r']
print a
c[:] = [x for x in c if x != 'r']
print a

print id(a), id(b), id(c)

If you want to learn more about generator expressions, read about generators and the iterator protocol in the python documentation, but you can postpone this a little if you are new to python.

Thanks for the quick reply, I really appreciate it.

This question has already been answered. Start a new discussion instead.