【问题标题】:Iterate again within the for loop在 for 循环中再次迭代
【发布时间】:2011-01-26 21:19:15
【问题描述】:

有没有办法在 for 循环中迭代 再次?例如:

for x in list:
  if(condition):
      #I'd like to grab the next iteration of the list 

所以如果我有 [1,2,3,4],我会先迭代 1,然后尝试在 for 循环中将迭代推进到 2,这样当循环再次开始时,它会是3.

可能吗?

我正在创建一个解析器,它读取 if 语句,然后想要向上读取行,直到遇到终止 if 语句的行。

【问题讨论】:

标签: python for-loop


【解决方案1】:

你可以这样做:

a = [1,2,3,4,5]
b = iter(a)

try:
    while True:
        c = b.next()
        if (condition):
            c = b.next()
except StopIteration:
    pass

【讨论】:

  • 除非你需要向后兼容 2.5,否则你应该使用next(b) 而不是b.next()
【解决方案2】:

如果您使用的项目是一个可迭代对象,您可以使用item.next() 来获取下一个元素。但如果需要,您需要确保获取 StopIteration 异常。

>>> it = iter(range(5))
>>> for x in it:
...     print x
...     if x > 3:
...         print it.next()
... 
0 1 2 3 4
Traceback (most recent call last):
  File "<stdin>", line 4, in <module>
StopIteration

【讨论】:

  • 这是我通常会做的。但是使用next(it) 而不是it.next(),因为这在Python3 中变成了it.__next__()
【解决方案3】:

您想要continue 语句。

for x in list:
  if(condition):
      continue

【讨论】:

  • 不太确定这是否是 OP 的想法(continue 跳到 到下一个项目),但这可能是他应该使用 ;) +1
  • 并非如此。我可能应该更清楚——如果我继续,我将失去我在代码中的位置。因此,如果某些事情是真的,让我 within if 语句,我想在该块中使用下一次迭代。如果我继续,控制权会直接返回到循环的开头,对吗?
  • @joslim:那么您将不得不处理自己迭代的丑陋胆量,因此您可以在迭代器上调用next。你不想去那里。在 99.99% 的情况下,您不需要这样做。重新考虑您的解决方案,您可以在没有continue 的情况下正常相处(抱歉,我含糊其辞,但如果我们不知道您到底想做什么,就很难提出替代方案)。
  • 啊,谢谢。我想它必须更符合 samurail 所说的内容——定义范围之外的变量,通知我所在的 for 循环以及我正在尝试做什么。如果您阅读我的编辑,我基本上只是试图解析出 if 语句的代码块。
【解决方案4】:
skip = False
for x in list:
    if skip:
        skip = False
        continue
    # Do your main loop logic here
    if (condition):
        skip = True

【讨论】:

    【解决方案5】:

    您可以使用while 循环而不是for。在伪代码中:

    idx = 0
    while idx < length(list)
        x = list[idx]
        ...
        if (condition)
            idx += 1
        ...
        idx += 1
    

    【讨论】:

    • 如果你正在迭代一个列表并且只会迭代列表,是的。一般来说,展开后的for 看起来会有所不同(在try ... except StopIteration: pass 中获取迭代器,while True,最后获取next(iterator))。
    【解决方案6】:

    你总是可以绕过 for 循环,直接使用迭代器:

    iter = list.__iter__()
    while True:
        x = iter.next()
        ...
        if (condition):
            x = iter.next()
        ...
    

    这将在到达列表末尾时引发 StopIteration 异常。

    【讨论】:

      【解决方案7】:

      我怀疑您解析 if 语句的方法不是解决问题的好方法。您还会发现您不能嵌套 IF 语句,也不能将它们全部放在一行中。这就是我将如何去做。

      a) 将您的语言转换为 BNF 形式。例如,对于 if 语句,它可能是

      ifstmnt ::=  IF &lt;condiftion> THEN &lt;trueblock> [ ELSE &lt;elseblock> ]
      
      statment ::= ifstmnt | assignstment | whilestmnt | forstmnt 
      

      b) 计算出您在每个时间点都在等待什么。在 IF 之后,您读取一个条件,直到您看到 THEN。

      c) 编写一个 getNextToken 例程,从您的源中读取字符,直到它有一个完整的令牌。令牌是一个可识别的单元 - IF、THEN、一个数字、一个符号。每次调用它时,它都会将令牌返回到缓冲区中。同时返回一个类型和一个值也很有用——它可以节省您在许多地方转换数字的时间。表驱动方法非常快速和灵活。

      d) 然后编写许多小程序来识别每种类型的语句。一个用于IF,一个用于条件,一个用于块,一个用于语句,一个用于表达式等。它们将相互调用并在识别到语句后返回。例如,条件表达式识别器将读取一个布尔表达式并吃掉所有名称、AND、OR 等,直到它向前看并看到 THEN。它无法处理 THEN 因此它存在,并且 IF 识别器发现令牌是 THEN,它读取下一个并调用识别器以获取一个块(可能需要 BEGIN、大量语句然后 END)。

      e) 每个例程都收集它需要的数据——条件、真块、假块,并根据需要进行处理。一种非常常见的处理方法是在内存中创建程序的树表示。程序员定义的名称在定义时被收集在字典中,并在使用时进行检查。

      f) 然后一个真正的编译器会尝试重新排列树以使事情更有效 - 但我建议这是未来的发展

      g) 最后的动作是遍历树,以某种方式评估它。如果您正在编写解释器,则可以计算值并随时存储 - 将值存储在字典中。如果您正在编写真正的编译器,则需要为链接器生成合适的输出。这是一项重大任务。

      查看 YACC 和 LEX。它们是为完成部分工作而设计的工具,可以节省您的时间。帮助您研究的术语是“词法分析”“解析器”等。

      祝你好运。你的项目很重要!

      另见http://nedbatchelder.com/text/python-parsers.html

      【讨论】: