Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does a for-loop with pop-method (or del statement) not iterate over all list elements

I am new to Python and experimenting with lists I am using Python 3.2.3 (default, Oct 19 2012, 20:13:42), [GCC 4.6.3] on linux2

Here is my samplecode

>>> l=[1,2,3,4,5,6]
>>> for i in l:
...     l.pop(0)
...     print(l)
... 

I would expect the following output

1
[2, 3, 4, 5, 6]
2
[3, 4, 5, 6]
3
[4, 5, 6]
4
[5, 6]
5
[6]
6
[]

Instead I am getting this

1
[2, 3, 4, 5, 6]
2
[3, 4, 5, 6]
3
[4, 5, 6]

The for-loop stops iterating after 3 turns. Can somebody explain why?

like image 514
user1913757 Avatar asked Dec 18 '12 18:12

user1913757


People also ask

Can a for loop be used to iterate over a list?

A for loop iterates through items the same way as while and do-while loops, but it can also iterate through a list or set.

Can you loop through multiple lists?

Iterate over multiple lists at a time We can iterate over lists simultaneously in ways: zip() : In Python 3, zip returns an iterator. zip() function stops when anyone of the list of all the lists gets exhausted. In simple words, it runs till the smallest of all the lists.

What is the use of pop () in a list?

List pop in Python is a pre-defined, in-built function that removes an item at the specified index from the list. You can also use pop in Python without mentioning the index value. In such cases, the pop() function will remove the last element of the list.

Which type of loop is most effective to iterate over a list?

While loop It works on any Collection ( List or Set ).


6 Answers

Unrolling a bit (the caret (^) is at the loop "index"):

your_list = [1,2,3,4,5,6]
             ^

after popping off the first item:

your_list = [2,3,4,5,6]
             ^

now continue the loop:

your_list = [2,3,4,5,6]
               ^

Now pop off the first item:

your_list = [3,4,5,6]
               ^

Now continue the loop:

your_list = [3,4,5,6]
                 ^

Now pop off first item:

your_list = [4,5,6]
                 ^

Now continue the loop -- Wait, we're done. :-)


>>> l = [1,2,3,4,5,6]
>>> for x in l:
...     l.pop(0)
... 
1
2
3
>>> print l
[4, 5, 6]
like image 192
mgilson Avatar answered Oct 28 '22 07:10

mgilson


Python doesn't support altering the length of a list while you iterate over it. Work on a copy or use a list comprehension instead.

Think about how Python is actually doing the for loop - it counts up through the elements, returning the item at the current index. When you remove one, the index means a different element.

like image 36
Gareth Latty Avatar answered Oct 28 '22 09:10

Gareth Latty


li = [1, 2, 3, 4, 5]

while li:
    # For descending order
    # print(li.pop())

    # For ascending order
    print(li.pop(0))
like image 40
Sourabh Biswas Avatar answered Oct 14 '22 12:10

Sourabh Biswas


You could use a while loop rather than a for loop for this task.

while len(some_list)>0 :
    some_list.pop(0)

A for loop will actually iterate over each item in the list, which will not work as the indices in the list will change with each deletion, and you will not end up getting all items.

However, a while loop will check a condition every time the loop is run, and if it is still true, run the code again. Here we specify that the length of the list has to be more than 0, i.e. there has to be content in the list.

like image 12
johnny brin Avatar answered Oct 28 '22 09:10

johnny brin


You have to be careful when attempting to modify collections you are iterating over. In this case, the list keeps track of the "current position" with a simple integer index. When you use pop(), everything changes index, and so elements are skipped.

On the first iteration of the loop, i is l[0]. Then you pop the list, then you access l[1], which is what originally was at l[2]. Then you pop the list, and the next iteration accesses l[2], which is what used to be at l[4], etc.

There's no need to pop elements in this code anyway, presumably you are doing something more complex in your real code.

like image 3
Ned Batchelder Avatar answered Oct 28 '22 08:10

Ned Batchelder


Code

l = [1,2,3,4,5,6]
for i in range(len(l)):
    l.pop(0)
    print(l)

returns

[2, 3, 4, 5, 6]
[3, 4, 5, 6]
[4, 5, 6]
[5, 6]
[6]
[]
like image 2
xcen Avatar answered Oct 28 '22 09:10

xcen