0

The out of range error shows when I try to remove an instance from a list but doesn't pop up when I just pass the statement?

for x in range(len(urls)-1):
  if urls[x] == None:
    urls.remove(urls[x])
walker38552
  • 35
  • 2
  • 8

2 Answers2

1

This is because you're removing from the list while starting the loop executing len(url) - 1 times. Total number of iterations will not be adjusted once you start removing from the list; and decreasing the length. Instead, you should use list comprehension for this.

new_list = [x for x in urls if x is not None]
BTables
  • 4,413
  • 2
  • 11
  • 30
  • 1
    Note the OP’s code doesn’t test the last entry in the list, (although maybe that’s not deliberate?) as posted it only iterates 0 to len(urls)-2. – DisappointedByUnaccountableMod Dec 13 '21 at 18:37
  • 1
    Note: If `urls` must be modified in-place (e.g. `urls` is a function argument, and the design is C++ reference-like, where the caller's copy of the `list` passed as `urls` should be modified), matching the behavior of the OP's original code, it's still easy to do this with a listcomp + slice assignment, e.g. `urls[:] = [x for x in urls if x is not None]` – ShadowRanger Dec 13 '21 at 18:38
0

This will happen even if there is a single None in your list.

The last index of the list which was valid before loop, will not be valid after popping a None because the list has shrunk by one.

Subsequent popping of your None element will result in subsequent shrinking of list and subsequent invalidity of 'second, third, fourth... from last' indexes.

Check workarounds here How to remove items from a list while iterating?

Edit

The above code runs loop on range(len(urls)-1) which means if there are 4 elements in list, then it becomes range(0,3) and in turn iterates over 0, 1, 2 only. Hence, the last index is never reached.

So the error will come after popping the second None. However, the intention seems to traverse the whole list and hence range(len(urls)) would be more appropriate in original code.

mr.loop
  • 818
  • 6
  • 20
  • 1
    This won't break if 0 or 1 elements are popped. The loop is using `range(len(urls) - 1)` – BTables Dec 13 '21 at 20:17
  • @BTables Ah yes I forgot to consider that although I think this is not being intended but a logical error. – mr.loop Dec 14 '21 at 05:01