Обход списка и изменение его во время обхода может привести к некоторому нелогичному поведению, такому как это. Делая remove()
элемента, на котором вы в данный момент находитесь, список изменяется таким образом, чтобы в следующий раз в цикле следующий элемент находился за пределами того места, где вы, как вы думаете, должны быть, поскольку список был сдвинут назад на один на операция remove()
.
>>> q = ['a', 'ab', 'abc', 'again', 'b', 'a1', 'c', 'a2', 'ack']
>>> for pos in q:
... if pos.startswith('a'):
... q.remove(pos)
...
>>> q
['ab', 'again', 'b', 'c', 'ack']
Здесь, когда первый элемент удален, список сдвигается вниз, поэтому первый элемент становится «ab». Затем в верхней части цикла «следующим» элементом является «abc», поскольку он сейчас находится на второй позиции, поэтому «ab» никогда не проверяется на удаление. Точно так же «снова» и «ack» не удаляются, потому что они никогда не тестировались. Фактически, «b» и «c» остаются в списке не потому, что они не начинаются с «a», но они также никогда не тестировались, так как список сместился и цикл пропустил их тоже!
Если вы перебираете копию или фрагмент вашего оригинального списка, это, вероятно, даст вам то, что вам нужно, но будьте осторожны с любым сценарием, в котором вы выполняете итерацию по чему-то, что обновляется одновременно.
>>> q = ['a', 'ab', 'abc', 'again', 'b', 'a1', 'c', 'a2', 'ack']
>>> for pos in q[:]:
... if pos.startswith('a'):
... q.remove(pos)
...
>>> q
['b', 'c']