Сократить список на месте совершенно безопасно, если вы сделаете это в обратном порядке!
>>> a=range(20)
>>> for i in reversed(range(len(a))):
... if a[i]%2: del a[i]
...
>>> a
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
Другой способ - переназначить весь фрагмент
>>> a=range(20)
>>> a[:]=(x for x in a if not x%2)
>>> a
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
Если элементы в списке уникальны, это тоже работает
>>> a=range(20)
>>> for item in reversed(a):
... if item%2: a.remove(item)
...
>>> a
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
Вот еще одно объяснение в ответ на комментарий Юрия
Предположим, у нас есть
>>> a=[0,1,2,3,4,5]
Теперь наивно пытаемся удалить 3-й и 4-й элементы
>>> del a[3]
>>> del a[4]
>>> a
[0, 1, 2, 4] # didn't work because the position of all the item with index >=3 was changed
Однако, если мы сделаем del
в обратном порядке
>>> a=[0,1,2,3,4,5]
>>> del a[4]
>>> del a[3]
>>> a
[0, 1, 2, 5] # this is the desired result
Теперь распространите эту идею на цикл for с условием удаления, и вы увидите, что удаление из активного списка возможно