There is a subtle problem with changing sequences in annotation loops (this can only happen with mutable sequences, eg lists). An internal counter is used to keep track of which element is used next, and this counter is incremented at each iteration. The loop ends when this counter reaches the length of the sequence. From this, removing the current (or previous) element from the sequence in the suite skips the next element (because the position of the next element is the index of the current element that has already been processed). It will be. Similarly, if you insert an element in the suite before the current element in the sequence, the current element will be treated again in the next week of the loop. These specifications lead to nasty bugs. This can be avoided by making a temporary copy using slices of the entire sequence.
official.py
for x in a[:]:
if x < 0: a.remove(x)
The element of foo_list
that is being turned by the for statement has been deleted in the sequence.
This may prevent the list from being turned to the end.
bug.py
for i in foo_list:
if thres >= i:
foo_list.remove(i)
First, turn all the for statements. Make a note of the element you want to erase. Turn the memod content with for to delete it.
Troublesome
no_good.py
memo = []
for i in range(len(foo_list)):
if thres >= foo_list[i]:
memo.append(foo_list[i])
for item in memo:
foo_list.remove(item)
Create a new list object by slicing the entire range of the list specified by the for statement. It's the same as ʻa = foo_list [:]` when you want to copy
beautiful.py
for i in foo_list[:]:
if thres >= i:
foo_list.remove(i)
By the way, if you just want to filter as above, the inclusion notation is better as pointed out by @shiracamus below. Then I will add the story of using him again.
@shiracamus Isn't it quicker to create a new list with comprehension than to remove it from the list?
foo_list = [i for i in foo_list if thres >= i]
Recommended Posts