22

我有这样的代码:

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

所以我想要的是修改 for 'inside' 循环的范围。

我编写了这段代码,期望在第一个循环期间 for 循环的范围会更改为 (1,7),但它没有发生。

相反,无论我输入什么数字,它都只运行 2 次。(我想要6次..在这种情况下)

我使用 print 像这样检查值:

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

怎么了?号码已更改。

我的想法哪里错了?

4

8 回答 8

39

该范围是根据loopcount调用时的值创建的——之后发生的任何循环计数都无关紧要。您可能想要的是一个 while 语句:

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

测试while条件i < loopcount是否为真,如果为真,则运行它包含的语句。在这种情况下,每次通过循环时,i 都会增加 1。由于第一次通过时 loopcount 设置为 7,因此循环将运行六次,因为 i = 1、2、3、4、5 和 6 .

一旦条件为假,当 时i = 7,while 循环停止运行。

(我不知道你的实际用例是什么,但你可能不需要分配 newcount,所以我删除了它)。

于 2012-08-10T16:26:22.040 回答
11

range()文档字符串:

range([start,] stop[, step]) -> 整数列表

返回一个包含整数等差数列的列表。range(i, j) 返回 [i, i+1, i+2, ..., j-1];start (!) 默认为 0。当给出 step 时,它指定增量(或减量)。例如,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().

于 2012-08-10T16:23:46.347 回答
5

user802500给出的while-loop答案可能是您实际问题的最佳解决方案;但是,我认为所提出的问题一个有趣且有启发性的答案。

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)
于 2012-08-10T18:58:11.247 回答
2

range()函数在for-loop 中求值时,它会生成一个值序列(即一个列表),用于迭代。

range()为此使用 的值loopcount。但是,一旦生成了该序列,您循环中所做的任何事情都不会更改该列表,即,即使您loopcount稍后更改,原始列表将保持不变 => 迭代次数将保持不变。

在你的情况下:

loopcount = 3
for i in range(1, loopcount):

变成

for i in [1, 2]:

所以你的循环迭代两次,因为你print在循环中有 2 个语句,你得到 4 行输出。请注意,您打印的值loopcount最初为 3,但随后被设置(并重置)为 7。

如果您希望能够动态更改迭代次数,请考虑改用while-loop。当然,您总是可以使用break语句提前停止/退出任何循环。

还,

   somestring = '7'
   newcount = int(somestring)

可以简化为

   newcount = 7
于 2012-08-10T16:24:06.820 回答
2

要专门解决“如何更改范围界限”的问题,您可以利用生成器的发送方法

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
于 2012-08-10T16:35:21.377 回答
1

看起来你的前提是你有一个默认的循环应该执行的次数,但是偶尔的情况是不同的。改用while循环可能会更好,但无论如何你都可以这样做:

if i == some_calculated_threshold:
    break

而是退出循环。

于 2012-08-10T16:27:11.753 回答
0

一旦设置了范围,您就无法增加迭代次数,但您可以提前突破,从而减少迭代次数:

for i in xrange(1, 7):
   if i == 2:
       break
于 2012-08-10T16:29:15.627 回答
0

adjustable_range这是Joel Cornett 提供的函数的更完整实现。

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
于 2012-08-10T17:13:49.393 回答