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

Изменение списка во время итерации

l  = range(100)                         
for i in l:                         
    print i,                         
    print l.pop(0),                  
    print l.pop(0)

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

Пожалуйста, объясните.

4b9b3361

Ответ 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)