Difference between .remove() and [1:]

Hello,
For the one of the tasks in the loops challenge I wrote the following solution:

#Write your function here
def delete_starting_evens(lst):
  for l in lst:
    if lst[0] % 2 == 0:
      lst.remove(lst[0])
    else:
      break
  return lst

It passes the first test however on the following test:

print(delete_starting_evens([4, 8, 10]))

It fails and returns a list containing 10.
When I substituted the remove line with a:

lst = lst[1:]

It worked perfectly. Could someone explain to me why and what is the difference between remove and the other method (I know that .remove removes the first incident of something but are there any other differences that could be relevant to what I described).

Thanks.

It has to do with how for...in works under the hood. When the for l in lst: line is first reached, an iterator is created. l is going to be assigned to lst[0] then lst[1] then lst[2], etc. until an invalid index is reached. When you remove an element of the list that you are iterating over, you get unexpected results. In your first iteration, l is assigned to 4. Your if condition evaluates to truthy, so lst.remove(lst[0]) is executed. Your lst now looks like [8, 10]. In the next iteration of the for...in loop, l is assigned to lst[1]. Which element is at index 1? That would now be 10. Your if condition, however, doesn’t use l (wouldn’t fix your issue if it did). It uses lst[0] which is 8. The condition evaluates to truthy, so 8 is removed leaving lst looking like: [10]. The next iteration of the for...in loop attempts to assign l to lst[2]. There is no element at index 2. The only valid index left is 0. Since there is no element to assign l to, the for...in loop is exited, and lst is returned giving you [10].
When you replaced the remove() operation with list slicing, your code re-assigns lst to a new list (the slice). This reassignment forces the for...in loop to generate a new iterator, so you don’t get the same unexpected behavior.

4 Likes

I see, I didn’t see properly through the logic of the iteration, the part where even tho now the lst[0] is different the list is at lst[1]. Thanks a lot.

1 Like