2016-10-21 3 views
1

Я нашел головоломку python и не могу понять, почему это работает.Изменение списка при повторении

x = ['a','b','c'] 
for m in x: 
    x.remove(m) 

и после этого цикла x = ['b']. Но почему?

Насколько я понимаю for ключевое слово неявно создает итератор для этого списка. Делает .remove() звонки __next__() метод так b пропущен? Я не могу найти никаких упоминаний об этом, но это мое лучшее предположение.

+2

Поскольку указатели не обновляются при удалении элемента. Последний индекс хранится через итерации, когда вы мутируете элементы, сдвигаются. –

+3

Это не документированное поведение и специфично для реализации. Избегайте. Здесь обсуждается: https://unspecified.wordpress.com/2009/02/12/thou-shalt-not-modify-a-list-during-iteration/ – cdarke

+0

Итератор, вероятно, имеет реализацию, подобную «i = 0 , а i

ответ

2

Здесь вы итерируете исходный список. На первой итерации вы удалили индексный элемент 0th, т. Е. a. Теперь, ваш список принадлежит: ['b','c']. На второй итерации ваш цикл for получит доступ к значению по индексу 1, но ваш индекс 1 имеет значение c. Таким образом, удаляется c. Следовательно, итоговый список будет ['b'].

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

x = ['a','b','c'] 
for m in list(x): # <-- Here 'list(x)' will create the copy of list 'x' 
        # for will iterate over the copy 
    x.remove(m) 

# updated value of 'x' will be: [] 

Примечания: Если это не для демонстрационной цели, и вы используете этот код для опорожнения списка, эффективный способ опустошения списка будет:

del x[:] 
+0

Получил, спасибо! – Paul

+1

Это заслуживает предупреждения из-за низких эксплуатационных характеристик. Каждое удаление из передней части списка приведет к тому, что каждый оставшийся предмет смещается (копируется!) Обратно на одну позицию. Если список большой, влияние производительности будет большим. Если ваш список длится 5 единиц, это будет всего 10 смен. Если это 1000 предметов, это будет 499500 смен. –

+0

Да, это правда. Если вы хотите просто сделать свой список пустым. Do, 'del x [:]'. Обновление ответа –

Смежные вопросы