ghostrider
ghostrider

Reputation: 5259

For-loop does not go over all objects

Why does this for-loop not go through all items:

 temp = 0

 for br in my_list :
    temp +=1
    #other code here
    #my list is not used at all, only br is used inside here
    my_list.remove(br)

 print temp
 assert len(my_list) == 0 , "list should be empty"

So, assertion fires. Then I added the temp counter and I do see that despite my list having 202 elements, the for loop processes only 101 of them. Why is that?

Upvotes: 2

Views: 780

Answers (4)

John La Rooy
John La Rooy

Reputation: 304433

If you really need to reclaim the memory used by the items in the lists ASAP, you can free them like this

for i, br in enumerate(my_list):
    #other code here
    my_list[i] = None

Except in Jython where Java will free them when it feels like it

Upvotes: 0

TWJW
TWJW

Reputation: 156

tobias_k is correct removing items from a list you are iterating over causes all sorts of problems.

In this case it's relatively easy to show that it is causing the iteration to skip, by printing the list on each loop, using the repl:

for br in my_list:
  my_list.remove(br)
  print my_list

This produces:

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

And finally leaves my_list containing: [1, 3, 5]

To do what you want, mic4ael is correct the simplest (although possibly not the most efficient) way is to take a copy of the list prior to iterating over it, as below:

my_list = [0,1,2,3,4,5]
for br in my_list[:]:     #The [:] takes a copy of my_list and iterates over it
  my_list.remove(br)
  print my_list

This produces:

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

Upvotes: 2

Atrotors
Atrotors

Reputation: 785

You shouldn't delete from the list you are iterating. Use this if you want to remove stuff

while list:
   item = list.pop()
   #Do stuff

Edit: if you want to know more about pop() look at the python doc

And if order is important, use pop(0). pop() removes the last item by default and if you want to go through your list in order you should use pop(0) that removes the first (index 0) item and returns it.

Edit2: Thanks to user Vincent for the while list suggestion.

Upvotes: 5

mic4ael
mic4ael

Reputation: 8310

Replace for br in my_list : with for br in my_list[:] :. Thanks to that you are going to iterate over a copy of the source list.

Upvotes: 3

Related Questions