Изменение количества итераций в цикле for

у меня есть такой код:

loopcount = 3
for i in range(1, loopcount)
   somestring = '7'
   newcount = int(somestring)
   loopcount = newcount

Итак, я хочу изменить диапазон для "внутри" цикла.

Я написал этот код, ожидая, что диапазон цикла for изменится на (1,7) во время первого цикла, но этого не произошло.

вместо этого, независимо от того, какое число я поставил, он работает только 2 раза. (Я хочу 6 раз.. в этом случае)

Я проверил значение с помощью печати, как это:

    loopcount = 3
    for i in range(1, loopcount)
       print loopcount
       somestring = '7'
       newcount = int(somestring)
       loopcount = newcount
       print loopcount
#output:
3
7
7
7

что не так? число были изменены.

где мое мышление неправильно?

8 ответов


диапазон создается на основе значения loopcount во время его вызова-все, что происходит с loopcount после этого, не имеет значения. То, что вы, вероятно, хотите, это заявление while:

loopcount = 3
i = 1
while i < loopcount:
    somestring = '7'
    loopcount = int(somestring)
    i += 1

на while проверяет, что условие i < loopcount является true, и если true, если запускает операторы, которые он содержит. В этом случае при каждом проходе через петлю i увеличивается на 1. Поскольку loopcount установлен в 7 в первый раз, цикл будет выполняться шесть раз, для i = 1,2,3,4,5 и 6.

как только условие ложно, когда i = 7, цикл while перестает выполняться.

(Я не знаю, каков ваш фактический вариант использования, но вам, возможно, не нужно назначать newcount, поэтому я удалил это).


С range() docstring:

range ([start,] stop [, step]) - > список целых чисел

возвращает список, содержащий арифметическую прогрессию чисел. диапазон (i, j) возвращает [i, i+1, i+2, ..., j-1]; start (!) по умолчанию 0. Когда шаг задан, он указывает приращение (или уменьшение). Например, range (4) возвращает [0, 1, 2, 3]. Конечная точка опущена! Это точно действительные индексы для списка из 4 элементы.

и range(1, 10), например, возвращает список типа: [1,2,3,4,5,6,7,8,9], таким образом, ваш код в основном делаю:

loopcount = 3
for i in [1, 2]:
    somestring = '7'
    newcount = int(somestring)
    loopcount = newcount

когда for цикл "инициализирован", список создается range().


на while-loop ответ user802500 вероятно, будет лучшим решением вашей реальной проблемы; однако, я думаю, что вопрос как просил есть интересный и поучительный ответ.

результат range () вызовов-это список последовательных значений. Цикл for повторяет этот список, пока он не будет исчерпан.

вот ключевой момент:вы можете мутировать список во время итерация.

>>> loopcount = 3
>>> r = range(1, loopcount)
>>> for i in r:
        somestring = '7'
        newcount = int(somestring)
        del r[newcount:]

практическим использованием этой функции является итерация по задачам в списке задач и позволяет некоторым задачам генерировать новые задачи:

for task in tasklist:
    newtask = do(task)
    if newtask:
        tasklist.append(newtask)

когда range ()


чтобы конкретно решить вопрос "Как изменить границы диапазона", вы можете воспользоваться отправка метод для генератора:

def adjustable_range(start, stop=None, step=None):
    if stop is None:
        start, stop = 0, start

    if step is None: step = 1

    i = start
    while i < stop:
        change_bound = (yield i)
        if change_bound is None:
            i += step
        else:
            stop = change_bound

использование:

myrange = adjustable_range(10)

for i in myrange:
    if some_condition:
        myrange.send(20) #generator is now bounded at 20

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

if i == some_calculated_threshold:
    break

чтобы выйти из цикла вместо этого.


вы можете увеличить количество итераций после того, как был установлен, но вы можете выйти досрочно, тем самым уменьшая количество повторов:

for i in xrange(1, 7):
   if i == 2:
       break

вот более полная реализация adjustable_range функция, предоставленная Джоэлом Корнеттом.

def adjustable_range(start, stop=None, step=None):
    if not isinstance(start, int):
        raise TypeError('start')
    if stop is None:
        start, stop = 0, start
    elif not isinstance(stop, int):
        raise TypeError('stop')
    direction = stop - start
    positive, negative = direction > 0, direction < 0
    if step is None:
        step = +1 if positive else -1
    else:
        if not isinstance(step, int):
            raise TypeError('step')
        if positive and step < 0 or negative and step > 0:
            raise ValueError('step')
    if direction:
        valid = (lambda a, b: a < b) if positive else (lambda a, b: a > b)
        while valid(start, stop):
            message = yield start
            if message is not None:
                if not isinstance(message, int):
                    raise ValueError('message')
                stop = message
            start += step