Перемещение итерации в цикл for

Итак, я хочу сделать что-то вроде этого:

for i in range(5):
    print(i);
    if(condition==true):
        i=i-1;

Однако по какой-либо причине, хотя я уменьшаю i, цикл, похоже, не замечает. Есть ли способ повторить итерацию?

Ответы

Ответ 1

for петли в Python всегда идут вперед. Если вы хотите иметь возможность двигаться назад, вы должны использовать другой механизм, например while:

i = 0
while i < 5:
    print(i)
    if condition:
        i=i-1
    i += 1

Или даже лучше:

i = 0
while i < 5:
    print(i)
    if condition:
        do_something()
        # don't increment here, so we stay on the same value for i
    else:
        # only increment in the case where we're not "moving backwards"
        i += 1

Ответ 2

Цикл Python с использованием range по-дизайну отличается от C/С++/Java for -loops. Для каждой итерации я устанавливается следующее значение range(5), независимо от того, что вы делаете с i между ними.

Вместо этого вы можете использовать while-loop:

i = 0
while i<5:
    print i
    if condition:
        continue
    i+=1

Но честно: я бы отступил и снова подумал о вашей первоначальной проблеме. Вероятно, вы найдете лучшее решение, поскольку такие циклы всегда подвержены ошибкам. Там есть причина, по которой Python for -loops, где он должен быть другим.

Ответ 3

У вас есть недоразумение о циклах в Python. Цикл for не заботится о том, что вы делаете с i на каждой итерации, потому что он вообще не связан с логикой цикла. Изменение i просто восстанавливает локальную переменную.

Вам нужно будет использовать цикл while для достижения ожидаемого поведения, когда состояние i влияет на поток управления цикла:

import random

i = 0
while i < 5:
    print(i)
    i += 1
    if random.choice([True, False]):
        i -= 1

Ответ 4

Использовать цикл while:

i = 0
while i < 5:
    print(i)
    if condition:
        i -= 1
    i += 1

Как уже упоминалось, это довольно унииоматический Python. Возможно, если вы опубликуете то, что вы пытаетесь достичь, мы можем дать несколько советов.

Ответ 5

range(5) создает список с числами 0 thru 4 в нем - [0, 1, 2, 3, 4].

Когда вы запустите цикл for через него, вы выполняете итерирование по списку. Выполнение i-= 1 уменьшит значение этого конкретного элемента списка, и итерация будет продолжена.

Как и другие ответы здесь, вы должны использовать цикл while.

i= 0
while i<5:
    # do stuff
    if #condition:
        i-= 1 # or +
    i+= 1

Ответ 6

Повторяя многие другие ответы и просто для полноты, вам нужно будет использовать while loop.

i = 0
while i < 5:
    print(i)
    if (not condition):
       i+=1

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

i = 0
while i < 5:
    print(i)
    if (condition):
        i -= 1
    else:
        i += 1

По существу, while i < 5 оценивает каждую итерацию и проверяет, есть ли i < 5. Таким образом, уменьшая/не меняя i, получаем следующее: (значения i)

Не меняется: 1->2->3-(condition satisfied)> 3 -> 4 -> 5

Уменьшение: 1->2->3-(condition satisfied)>2 -> 3 -> 4 -> 5

Причина, по которой i=i-1 в вашем цикле for не делает повторение, итерация проста. В цикле for i присваивается значение следующего элемента в цикле for. Python меньше заботится о том, что вы делаете с i, если он может назначить ему следующий элемент. Таким образом, цикл цикла for i in <your_iterable>:<do whatever> ближе к этому:

_i = 0
_length = len(<your_iterable>)
while _i < _length:
    i = _i
    _i += 1
    <do whatever>

Однако в этой аналогии вы не сможете получить доступ к исходным переменным _ (_i, _length). Вот как я упрощаю логику for loop. Обратите внимание, что независимо от того, для чего назначен i, он будет назначен _i на следующей итерации, и цикл действительно не заботится о том, что i.

Ответ 7

В Python можно настроить двусторонний обмен между итератором (что происходит после in в цикле for..in) и его потребителем (код внутри цикла). Для этого вы можете использовать send в потребительском коде, чтобы "ввести" значение в генератор. В вашем случае вы можете просто отправить обратно текущее значение после выполнения условия и обернуть вызов range в генераторе, который повторяет все, что отправлено обратно. Вот вам какой-то код для игры, преднамеренно многословный для ясности:

def repeateble(it):
    buf, it = None, iter(it)
    while True:
        if buf is None:
            # the buffer is empty, send them the next elem
            val = next(it)
        else:
            # there something in the buffer
            # let send that back
            val = buf

        # send the value and wait what they say
        back = yield val

        if back:
            # they've sent us something!
            # give them some dummy value as a result of send()
            yield None 
            # and save what they've sent in a buffer
            # for the next iteration
            buf = back

        else:
            # they haven't sent anything
            # empty the buffer
            buf = None


from random import randint

# create a repeateble generator
rng = repeateble(range(100))

for x in rng:
    print(x)

    # check "some condition"...
    if randint(1, 100) > 80:
        print('repeat:')
        # send the current value back to the generator
        # it will be returned on the next iteration
        rng.send(x)

Ответ 8

Вы можете использовать readlines, если вы просматриваете файл и извлекаете предыдущие строки, основываясь на условии.


with open("myfile.txt", "r") as f:
    text = f.readlines()
    for row in range(0, len(text)):
        if re.search("Error", text[row]):
            print(text[row-1].strip())