Mystery with remove and pop in Python lists

Thanks Vishal for his inputs on this..

According to python docs

list.remove(x)
Remove the first item from the list whose value is x. It is an error if there is no such item.
list.pop([i])
Remove the item at the given position in the list, and return it. If no index is specified, a.pop() removes and returns the last item in the list. (The square brackets around the i in the method signature denote that the parameter is optional, not that you should type square brackets at that position. You will see this notation frequently in the Python Library Reference.)

Lets try out some code around these two functions

Scenario 1

[sourcecode language=”python”]
list = range(10)
for iter in list:
list.pop()
print list
[/sourcecode]

Output of the above code snippet is:
[0, 1, 2, 3, 4, 5, 6, 7, 8]
[0, 1, 2, 3, 4, 5, 6, 7]
[0, 1, 2, 3, 4, 5, 6]
[0, 1, 2, 3, 4, 5]
[0, 1, 2, 3, 4]

Change in expectation? While one would expect all the elements would be removed from the list, only the later half got removed.
This is because,

iteration iter elements poped
1 0 9
2 1 8
3 2 7
4 3 6
5 4 5
6 5 No element in list?

So when iter become 5 there is no element at that index location

Scenario 2

[sourcecode language=”python”]
list = range(10)
for element in list:
list.remove(element)
print list
[/sourcecode]

Output of the above code snippet is:
[1, 2, 3, 4, 5, 6, 7, 8, 9]
[1, 3, 4, 5, 6, 7, 8, 9]
[1, 3, 5, 6, 7, 8, 9]
[1, 3, 5, 7, 8, 9]
[1, 3, 5, 7, 9]

Again, I would expect all elements to be removed. But now I’m smart to understand,

iteration iter element removed
1 0 0
2 1 list[1] = 2
3 2 list[2] = 4
4 3 list[3] = 6
5 4 list[4] = 8
6 5 No element?

2 thoughts on “Mystery with remove and pop in Python lists

  1. using a while list with .pop() eliminates the problem:

    list = range(10)
    i=0
    length = len(list)
    while i < length:
    list.pop()
    i += 1
    print list

    be sure to initialize length to the len(list) and use length rather than len(list) as the upper bound of i in the loop. Otherwise, as list gets shorter in each pass through the loop, len(list) gets smaller, and you'll only pop half the list items.

  2. Problems like these are easiest solved by reversing the list
    list = range(10)
    for iter in list[::-1]:
    list.pop()
    print list

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.