для циклов в Python-как изменить i внутри цикла
этот код был написан на Python 3.6 В ноутбуках Jupyter. На других языках я уверен, что построил петли, которые выглядели так:
endRw=5
lenDF=100 # 1160
for i in range(0, lenDF):
print("i: ", i)
endIndx = i + endRw
if endIndx > lenDF:
endIndx = lenDF
print("Range to use: ", i, ":", endIndx)
# this line is a mockup for an index that is built and used
# in the real code to do something to a pandas DF
i = endIndx
print("i at end of loop", i)
в тестировании, однако,i не сбрасывается до endIndx и поэтому цикл не создает предполагаемые значения Индекса.
я смог решить эту проблему и получить то, что я искал, построив цикл while следующим образом:
endRw=5
lenDF=97 # 1160
i = 0
while i < lenDF:
print("i: ", i)
endIndx = i + endRw
if endIndx > lenDF:
endIndx = lenDF
print("Range to use: ", i, ":", endIndx)
# this line is a mockup for an index that is built and used
# in the real code to do something to a pandas DF
i = endIndx
print("i at end of loop: ", i)
вопрос: есть ли способ, чтобы изменить i изнутри the for цикл в python? Есть ли способ сделать то, что я сделал с while петли с помощью for цикл в Python?
решена проблема с while но просто любопытно об этом.
5 ответов
for циклы работают на iterables. В for i in range(0, lenDF), i присваивается следующее значение в диапазоне на каждом круге цикла независимо от того, как он используется в цикле. Вопрос в том, есть ли чистый способ написать итерацию, которая делает то, что вы хотите. В этом случае все, что вам нужно, - это перейти на фиксированный шаг и настроить длину последнего шага для учета конца данных.
endRw=5
lenDF=97 # 1160
for i in range(0, lenDF, endRw):
endIndx = min(i+endRw, lenDF)
print("Range to use: ", i, ":", endIndx)
вы can измените переменную цикла в for цикл, проблема в том, что for петли в Python не похожи на" старый стиль"for петли, например, Java, но больше похоже на" новый стиль"for-each петли.
В Python, for i in range(0, 10): не ведет себя как for (int i = 0; i < 10; i++) {, а как for (int i : new int[] {0, 1, ..., 10}}.
то есть на каждой итерации цикла головка цикла не будет изменять переменную цикла (например, увеличивать ее), но присвоить ему новое значение, т. е. следующее значение из заданного iterable (a range в вашем случае). Таким образом, любые изменения, которые вы сделали в предыдущей итерации перезаписываются.
если вы хотите зациклить известное количество итераций или для каждого элемента в iterable, используйте for цикл, но если вы хотите цикл до определенного условия (больше не), как в вашем случае, используйте while.
этот ответ вряд ли будет полезен, но так как вы были просто любопытно:
Ближе всего, я думаю, к тому, что вы хотите сделать, будет использовать генератор и его send способ:
>>> def jumpable_range(start, stop):
... i = start
... while i <= stop:
... j = yield i
... i = i + 1 if j is None else j
...
>>> R = jumpable_range(2, 10)
>>>
>>> for i in R:
... if i==5:
... i = R.send(8)
... print(i)
...
2
3
4
8
9
10
>>>
принимая первоначальный вопрос буквально:
- @Tobias_k обеспечивает хорошее объяснение когда использовать
whileиforпетли, и случай использования этого вопроса подходитwhileлучше (по крайней мере для Python). Короче говоря: вы не можете напрямую изменитьiнаfor i inиз-за того, как этот код работает под обложками в Python. Так чтоwhileследует использовать для случая использования, когда вам нужно изменить счетчик внутри цикла (в Питон.) - @tdelaney дает хороший ответ с точки зрения рефакторинга кода с помощью Python
forцикл, учитывая поведение Python (принято отвечать на этот вопрос). - @PaulPanzer обеспечивает понятий это, хотя и слишком сложно, полезно для студентов, чтобы исследовать новые концепции; но ответ решает
forпроблема цикла с помощьюwhileцикл внутри итератора и вызов этого вforпетля.
тем не менее, концепции исследовали, что играть в использовании yield и итераторы стоит изучить. Если мы возьмем эти понятия и попытаемся переписать исходный код, чтобы использовать их, вот как будет выглядеть этот код:
def jumpable_range(start, stop):
i = start
while i <= stop:
j = yield i
i = i + 1 if j is None else j
endRw=5
lenDF=97 # 1160
Q = jumpable_range(0,lenDF)
for i in Q:
print("i: ", i)
endIndx = i + endRw
if endIndx > lenDF:
endIndx = lenDF
if i == endIndx: break
print("Range to use: ", i, ":", endIndx)
# this line is a mockup for an index that is built and used
# in the real code to do something to a pandas DF
i = Q.send(endIndx-1)
print("i at end of loop", i)
вы всегда можете задать значение i на for петли. Проблема в том, что ваш оператор установки значения находится перед неявным for оператор значения установки цикла и покрытый последним. Вы не можете изменить правило, чтобы сделать последнее утверждение бесполезным. Ты не должен этого делать, даже ты можешь. Просто измените, чтобы использовать правильную условную переменную.