Подтвердить что ты не робот

Почему не безопасно изменять последовательность, повторяющуюся?

Неправильно изменять последовательность, повторяющуюся в цикле (это может произойти только для изменяемых типов последовательностей, таких как списки). Если вам нужно изменить список, который вы повторяете (например, чтобы дублировать выбранные элементы), вы должны перебирать копию. Нотация среза делает это особенно удобным:

   >>> for x in a[:]: # make a slice copy of the entire list
   ...    if len(x) > 6: a.insert(0, x)
   ... 
   >>> a
   ['defenestrate', 'cat', 'window', 'defenestrate']

почему не безопасно просто делать for x in a??

4b9b3361

Ответ 1

Без слишком технического:

Если вы выполняете итерацию через изменяемую последовательность в Python, и последовательность изменяется при повторении, не всегда ясно, что произойдет. Если вы вставляете элемент в последовательность во время итерации через него, что теперь разумно будет считаться "следующим" элементом в последовательности? Что делать, если вы удаляете следующий объект?

По этой причине итерация с помощью изменяемой последовательности во время ее изменения приводит к неуказанному поведению. Все может произойти, в зависимости от того, как именно реализован список.: -)

Ответ 2

Это обычная проблема на многих языках. Если у вас есть линейная структура данных, и вы повторяете ее, что-то должно отслеживать, где вы находитесь в структуре. Это может быть текущий указатель или указатель, но это какой-то палец, указывающий на "текущее место".

Если вы изменяете список во время итерации, этот курсор, вероятно, будет неправильным.

Общей проблемой является то, что вы удаляете элемент под курсором, все слайд вниз, следующая итерация цикла увеличивает курсор, и вы случайно пропустили элемент.

Некоторые реализации структуры данных предлагают возможность удалять элементы во время итерации, но большинство из них не работает.

Ответ 3

Когда вы изменяете коллекцию, в которой вы выполняете итерацию, итератор может вести себя непредсказуемо, например, пропускать элементы или возвращать один и тот же элемент дважды.

Этот код цикл бесконечно, когда я запускаю его:

>>> a = [ 'foo', 'bar', 'baz' ]
>>> for x in a:
...    if x == 'bar': a.insert(0, 'oops')

Это потому, что итератор использует индекс, чтобы отслеживать, где он находится в списке. Добавление элемента в начале списка приводит к тому, что элемент "bar" возвращается снова, вместо того, чтобы итератор переходил к следующему элементу.