Python Forum
Error in loops, new to Python
Thread Rating:
  • 1 Vote(s) - 3 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Error in loops, new to Python
#11
Maybe because you're only modifying things you've already iterated over. Regardless, you probably shouldn't do it, and you definitely shouldn't rely on it working right all the time.

In this case, you don't need to (since you only iterate over the list once, and do the same thing with every value in the list regardless of what that value is), and for the same reason, you also don't need a while loop, since it'll only ever run once anyway.
Reply
#12
(Apr-24-2017, 03:43 AM)nilamo Wrote: Modifying a list while you're in the middle of iterating over that same list is very dangerous.
Usually - from the last time I SNAFUed this way (several years ago  Blush) - iterator skips element on each deletion. It's not dangerous - it's a bug

(Apr-23-2017, 10:19 AM)smbx33 Wrote: I made minor modifications to the existing code and provided explanation. 

.....
while len(list_) >0: # here you had list[0] I think you wanted to stop when length reached 0
    for amount in list_: # for loop will go through the list_ of numbers one amount at a time
      .....
        list_.remove(amount) #this is to remove items from your list!

# you don't need to check the counter.  so the if statement could be deleted or reworded so if the program is run and no items are on the list it says NO ITEMS! else it prints A
Though it works - as I have pointed out in previous post, deleting an element of a list while iterating over that list is a bug, which is in this case accidentally compensated for by the external loop. In another scenario, it will not work as expected

This solves the issue
while list_:
    s += list_[0]
   .....
   list_.pop(0)
This way you always process first element of the list - while list is not empty, and you don't perform any unnecessary actions
Test everything in a Python shell (iPython, Azure Notebook, etc.)
  • Someone gave you an advice you liked? Test it - maybe the advice was actually bad.
  • Someone gave you an advice you think is bad? Test it before arguing - maybe it was good.
  • You posted a claim that something you did not test works? Be prepared to eat your hat.
Reply
#13
Iterate over the copy of the list while modifying the original.

for element in list_[:]:
    # modify list_
"As they say in Mexico 'dosvidaniya'. That makes two vidaniyas."
https://freedns.afraid.org
Reply
#14
I think the easy solution is to just iterate over a copy of the list, ie: for x in some_list[:]:, but then if the list is large (or is a generator and doesn't exist fully yet), that could just eat memory. Maybe for x in (item for item in some_list):? That way you can modify the original list, without changing how you iterate. Could make for confusing results sometimes, though.
Reply
#15
No problem with the big lists:
for element in iter(list_[:]):
    # do something
"As they say in Mexico 'dosvidaniya'. That makes two vidaniyas."
https://freedns.afraid.org
Reply
#16
I think a little illustration is in order to show the folly of removing an element from a list while iterating over it.
In [1]: l = list(range(10))

In [2]: for elem in l:
   ...:     l.remove(elem)
   ...:     print(elem)
   ...:
0
2
4
6
8
And this shows how OP's code worked
In [4]: while l:
   ...:     for elem in l:
   ...:         l.remove(elem)
   ...:         print(elem)
   ...:
0
2
4
6
8
1
5
9
3
7
Test everything in a Python shell (iPython, Azure Notebook, etc.)
  • Someone gave you an advice you liked? Test it - maybe the advice was actually bad.
  • Someone gave you an advice you think is bad? Test it before arguing - maybe it was good.
  • You posted a claim that something you did not test works? Be prepared to eat your hat.
Reply
#17
(Apr-24-2017, 06:41 PM)volcano63 Wrote:
(Apr-24-2017, 03:43 AM)nilamo Wrote: Modifying a list while you're in the middle of iterating over that same list is very dangerous.
Usually - from the last time I SNAFUed this way (several years ago  Blush) - iterator skips element on each deletion. It's not dangerous - it's a bug
For me it looks like appropriate behaviour - from my understanding list iterator (created with for clause) only keeps information about list object and current index. For i-th loop it gives i-th item from the actual list - and if in i-th loop i-th item is different than i-th item before start of loop, well, its not for/iterator problem, but yours. So if you are removing items from the start of the list  while looping over it, it looks like it skips every second item, while if you are removing items from the end of the list, it looks like iteration over first half of the list only. Indeed it makes things rather confusing , so its bettter to avoid it...

(Apr-24-2017, 06:47 PM)nilamo Wrote: I think the easy solution is to just iterate over a copy of the list, ie: for x in some_list[:]:, but then if the list is large (or is a generator and doesn't exist fully yet), that could just eat memory.  Maybe for x in (item for item in some_list):?  That way you can modify the original list, without changing how you iterate.  Could make for confusing results sometimes, though.
Such generator expression would not work, it references original list too, changes would "propagate".
Reply
#18
(Apr-24-2017, 07:50 PM)zivoni Wrote:
(Apr-24-2017, 06:41 PM)volcano63 Wrote: Usually - from the last time I SNAFUed this way (several years ago  Blush) - iterator skips element on each deletion. It's not dangerous - it's a bug
For me it looks like appropriate behaviour -
Let me clarify - I was not talking about the interpreter behavior; I was referring specifically to implementation - that using iterator that way is a bug in the implementation. I thought that it was rather obvious  Wall
Test everything in a Python shell (iPython, Azure Notebook, etc.)
  • Someone gave you an advice you liked? Test it - maybe the advice was actually bad.
  • Someone gave you an advice you think is bad? Test it before arguing - maybe it was good.
  • You posted a claim that something you did not test works? Be prepared to eat your hat.
Reply
#19
Thank you all, I have a deeper understanding of why I was wrong in deleting items off the same list that I am iterating over :P Even though its a bug and gives undesired results(sometimes). Since it was my very first time using remove() as a function, I was very content watching the desired results populate. I now know that if you are removing items from the start of the list while looping over it, it looks like its skips an item, but even if the item is skipped, the while loop will just tell it to iterate again until no items on the list. But that the practice is still confusing and should be avoided.
Reply
#20
>>> items = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> for ndx, item in enumerate(items):
...   print("{0} => {1}".format(ndx, item))
...   items.remove(item)
...
0 => 0
1 => 2
2 => 4
3 => 6
4 => 8
5 => 10
>>> items
[1, 3, 5, 7, 9]
The for loop keeps track of what index it's at, but when you change the underlying list, the index stays the same... it's just going to refer to a different element. So you don't iterate over the whole list, but it is at least predictable. Predictable, at least, if that's what you were expecting. I still think you either shouldn't modify the list, or use a while loop and only ever use the first element.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  New to python! Loops Seeley307 3 61,680 May-15-2020, 02:27 PM
Last Post: ibreeden
  Python for loops giving error Petrus 12 5,537 Jan-09-2019, 08:02 AM
Last Post: Petrus

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020