Изменение списка во время итерации
l = range(100)
for i in l:
print i,
print l.pop(0),
print l.pop(0)
Приведенный выше код python дает результат, отличный от ожидаемого. Я хочу перебрать элементы, чтобы я мог пропустить элемент во время цикла.
Пожалуйста, объясните.
Ответы
Ответ 1
Я был укушен раньше (чужой) "умный" код, который пытается изменить список, итерации по нему. Я решил, что никогда не сделаю этого ни при каких обстоятельствах.
Вы можете использовать оператор slice mylist[::3]
, чтобы перейти к каждому третьему элементу в вашем списке.
mylist = [i for i in range(100)]
for i in mylist[::3]:
print(i),
Другие моменты моего примера относятся к новому синтаксису в python 3.0.
- Я использую понимание списка для определения mylist, потому что он работает в Python 3.0 (см. ниже).
- print - это функция в python 3.0
Диапазон Python 3.0() теперь ведет себя как xrange(), используемый для ведения, за исключением того, что он работает со значениями произвольного размера. Последнее больше не существует.
Ответ 2
Никогда не изменяйте контейнер, который вы зацикливаете, потому что итераторы на этом контейнере не будут проинформированы о ваших изменениях и, как вы заметили, вполне вероятно, создадут совершенно другой цикл и/или неправильный, В обычных случаях цикличность на копии контейнера помогает, но в вашем случае ясно, что вы этого не хотите, так как контейнер будет пуст после 50 ножек цикла, и если вы затем попробуете снова выскочить, вы получите исключение.
Что бы ни было, но ясно, какое поведение вы пытаетесь достичь, если оно есть?! Может быть, вы можете выразить свои желания с помощью while
...?
i = 0
while i < len(some_list):
print i,
print some_list.pop(0),
print some_list.pop(0)
Ответ 3
Общее эмпирическое правило состоит в том, что вы не изменяете список collection/array/list во время итерации по нему.
Используйте вторичный список для хранения элементов, на которые вы хотите действовать, и выполните эту логику в цикле после вашего начального цикла.
Ответ 4
Попробуйте это. Это позволяет избежать мутации вещи, которую вы повторяете, что обычно является запахом кода.
for i in xrange(0, 100, 3):
print i
См. xrange
.
Ответ 5
Используйте цикл while, который проверяет правдивость массива:
while array:
value = array.pop(0)
# do some calculation here
И он должен делать это без каких-либо ошибок или смешного поведения.
Ответ 6
Я думаю, это то, что вы хотите:
l = range(100)
index = 0
for i in l:
print i,
try:
print l.pop(index+1),
print l.pop(index+1)
except:
pass
index += 1
Очень удобно кодировать, когда количество элементов, которые нужно выбить, - это решение времени выполнения.
Но он работает с очень плохой эффективностью, и код трудно поддерживать.
Ответ 7
Этот синтаксис фрагмента делает копию списка и делает то, что вы хотите:
l = range(100)
for i in l[:]:
print i,
print l.pop(0),
print l.pop(0)