如何在for循环中跳过几次迭代

33
在Python中,我通常通过循环范围来循环遍历,方法是:
for i in range(100): 
    #do something

但是现在我想跳过循环中的几个步骤。更具体地说,我想要像continue(10)这样的东西,这样它就会跳过整个循环并将计数器增加10。如果我在C中使用for循环,我只需将10加到i上,但在Python中,这并不起作用。

6个回答

37

for 循环中,你不能改变目标列表(在本例中是 i)。请改用 while 循环:

while i < 10:
    i += 1
    if i == 2:
        i += 3

或者,使用可迭代对象并递增:

from itertools import islice

numbers = iter(range(10))
for i in numbers:
    if i == 2:
        next(islice(numbers, 3, 3), None)  # consume 3

通过将iter()的结果赋值给本地变量,我们可以在循环内部使用标准迭代工具(next()或这里的缩短版itertools消耗配方)来推进循环序列。当迭代一个迭代器时,for通常会为我们调用iter()


7
我想这可能是事实,然而while循环确实有些悲伤。 - Alex S
最终还是用了while循环!非常感谢! - Alex S
@AlexS 如果你正在遍历数字,那没问题 - 但如果你将这些数字用作列表或其他数据结构的索引,请不要这样做。通过索引进行迭代是一种不好的方式。 - Gareth Latty

26

最好的方法是给迭代器分配一个名称 - 常见的情况是具有可迭代对象而不是迭代器(区别在于可迭代对象 - 例如列表 - 在每次迭代时都从开头开始)。在这种情况下,只需使用内置函数iter()

numbers = iter(range(100))

然后您可以在循环中使用名称将其推进。最好的方法是使用itertools consume()配方 - 因为它很快(它使用itertools函数来确保迭代发生在低级别代码中,使消耗值的过程非常快,并且避免通过存储已使用的值来使用内存):

from itertools import islice
import collections

def consume(iterator, n):
    "Advance the iterator n-steps ahead. If n is none, consume entirely."
    # Use functions that consume iterators at C speed.
    if n is None:
        # feed the entire iterator into a zero-length deque
        collections.deque(iterator, maxlen=0)
    else:
        # advance to the empty slice starting at position n
        next(islice(iterator, n, n), None)

通过这样做,你可以做类似于:

numbers = iter(range(100))
for i in numbers: 
    ...
    if some_check(i):
        consume(numbers, 3)  # Skip 3 ahead.

2
请注意,即使在Python 3中,您仍然需要在range()上调用iter()才能使其正常工作。Python 3的range()对象是一个序列(可迭代对象),而不是迭代器。 - Martijn Pieters
@MartijnPieters 非常好的观点。已编辑。我很少迭代范围,所以忘记了这一点。 - Gareth Latty
+1,这似乎是最快的方式,而且不太复杂。 - 2rs2ts

5

为什么不直接将值设置为跳过至?像这样:

skip_until = 0
for i in range(100):
    if i < skip_until:
        continue
    if SOME_CONDITION:
        skip_until = i + 10
    DO_SOMETHING()

其中SOME_CONDITION是导致你跳过的任何条件,而DO_SOMETHING()则是实际的循环内容。


值得注意的是,这需要在Python中执行循环,并且每次分配名称 - 虽然在大多数情况下不太可能成为问题,但从这个意义上讲,它的效率要低得多。 - Gareth Latty
是的,但考虑到问题的简单性,我认为他想要一个简单的答案;如果循环/跳过的次数很少,那么操纵迭代器似乎有些过度。 - Josh Buell

1
for i in range(0, 100, 10):
    print(i)

将会打印出0、10、20等。

1
嗨,虽然这跳过了前10个值,但我认为提问者更感兴趣的是如何在循环中跳转到任意值。请参考顶部答案的示例。 - seth
你肯定也不需要 Python 3.3 来完成这个任务。 - Gareth Latty

0

这是我一直在使用的东西。你可以使用以下代码来获得运行代码时的10%概率:

import random
for i in range(1000000):
    if random.random() > 0.1:
        continue:
    # your code

-2

一个迷人而简单的形式是这样的:

>>> for i in range(5,10):
...     print (i)
... 
5
6
7
8
9

其中 5 是开始迭代的索引。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接