Перемещение итерации в цикл 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())