Я обсуждал это некоторое время, потому что подобные вопросы задавались много раз здесь. Но это просто уникально, чтобы получить преимущество от сомнений. (Тем не менее, я не буду возражать, если другие голосуют, чтобы закрыть.) Вот визуальное объяснение того, что происходит.
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] <- b = 0; remove? no
^
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] <- b = 1; remove? yes
^
[0, 2, 3, 4, 5, 6, 7, 8, 9] <- b = 3; remove? no
^
[0, 2, 3, 4, 5, 6, 7, 8, 9] <- b = 4; remove? yes
^
[0, 2, 3, 5, 6, 7, 8, 9] <- b = 6; remove? no
^
[0, 2, 3, 5, 6, 7, 8, 9] <- b = 7; remove? yes
^
[0, 2, 3, 5, 6, 8, 9] <- b = 9; remove? no
^
Поскольку никто другой не имеет, я попытаюсь ответить на ваши другие вопросы:
Почему ошибка не указана, чтобы указать, что базовый итератор изменяется?
Бросать ошибку без запрещая много совершенно допустимые конструкции петель, Python бы знать много о том, что происходит, и это, вероятно , придется получить эту информацию во время выполнения. Вся эта информация потребует времени для обработки. Это сделало бы Python намного медленнее, только в том месте, где скорость действительно рассчитывается - цикл.
Изменились ли механики из более ранних версий Python в отношении этого поведения?
Короче говоря, нет. Или, по крайней мере, я очень сомневаюсь в этом, и, конечно, он вел себя так, так как я изучил Python (2.4). Честно говоря, я бы ожидал, что любая простая реализация изменчивой последовательности будет вести себя именно таким образом. Любой, кто знает лучше, пожалуйста, поправьте меня. (На самом деле быстрый поиск документов подтверждает, что текст, который цитировал Микола , был в учебнике с версии 1.4 !)