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

list = range(10)
for iter in list:
    list.pop()
    print list

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

list = range(10)
for element in list:
    list.remove(element)
    print list

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?
Advertisements

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

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s