【问题标题】:python: exit out of two loopspython:退出两个循环
【发布时间】:2011-03-22 09:33:28
【问题描述】:
  for row in b:
    for drug in drug_input:
      for brand in brand_names[drug]:

如何从第三个循环退出当前循环并转到for row in b: 的下一个值?

【问题讨论】:

  • 我可能会尝试包装这个块并通过加注来打破它。
  • 请问内循环中的什么条件会强制break
  • 好的。这里有很多答案,所有这些都是正确的,因为它们确实打破了两个循环。但我不认为你写的这段代码是正确的。 为什么你要执行这个迭代?回顾最后一天的帖子,我认为b 是包含一些药物的 CSV 行列表。为什么您需要针对所述 CSV 的每一行迭代您知道的每种药物?
  • 请扩展您的示例 - 可能有更好的方法来解决它,而无需从外循环中断。
  • Python 已经转到:entrian.com/goto ;-)(请不要在实际代码中使用它)

标签: python


【解决方案1】:

如果您有太多嵌入式循环,则可能是重构的时候了。在这种情况下,我认为最好的重构是将循环移动到函数中并使用return 语句。这将强制退出任意数量的循环。例如:

def example(self, drug_input):
    ok = False
    for x in drug_input["names"]:
        for y in range(drug_input["number_of_drugs"]):
            for z in drug_input["list_of_drugs"]:
                # do stuff
                if ok:
                    return drug_costs

现在,也许像这样重新构造你的逻辑很棘手,但我敢打赌,重构会在其他方面有所帮助。

【讨论】:

    【解决方案2】:
    for a in aa:
         for b in bb:
             for c in cc:
                if c == a[b]:
                    break
             else:
                 continue
             break
    

    Python 支持for...else 语句。如果内部 break 未被触发,则评估 else 块。

    【讨论】:

    • 抱歉,您能告诉我这对当前内容有什么影响吗?
    【解决方案3】:

    我看到请求此功能的最新 PEP 是 3136(被拒绝):http://mail.python.org/pipermail/python-3000/2007-July/008663.html

    对于您想要做的事情,我能看到的最接近和最干净的事情是执行以下操作(并且由于即使类型名称也是有范围的,您可以在所需的函数中声明 LocalBreak):

    class LocalBreak(Exception): pass
    
    try:
       for i in ...:
           for h in ...:
               for j in ...:
                  if should_break(j):
                     raise LocalBreak()
    except LocalBreak:
       pass
    

    【讨论】:

      【解决方案4】:

      异常处理优于在 IMO 各处设置变量

      for row in b:
          for drug in drug_input:
              try:
                  for brand in brand_names[drug]:
                      if some_condition:
                          raise StopIteration
              except StopIteration:
                  break
      

      【讨论】:

      • 例外仅适用于特殊情况!
      • "这是从 Exception 而不是 StandardError 派生的,因为这在其正常应用程序中不被视为错误。" docs.python.org/library/…
      • 好吧,这是一个很好的回归 :) 但说真的,不要处理控制流的异常。任何语言。 try-except 处理程序是一种非常非常普遍的视觉提示,用于表示“刚刚发生了一些不寻常的事情”。
      • 如果要使用异常,为什么不将异常处理上移一级而不使用break呢?
      • @cjrh - 是的,我基本同意。我通常不会滥用这样的异常,但在这种情况下,我发现它更优雅,并且这个特殊的异常就是为此而设计的......停止迭代。我还认为这更容易阅读,我们都知道它很重要。 :>)
      【解决方案5】:

      我会考虑将 两个内部循环放在函数中 并从那里使用 return。可能会重新考虑您正在做什么以及如何提供更好的替代方案。

      您能否提供您当前的伪代码、输入和输出,以便我们可以尝试首先消除对中断的需求?我们需要看看循环变量在哪里使用,或者更好的是,处理的目标是什么。

      【讨论】:

        【解决方案6】:

        如果您在一种方法中有三个级别的循环,那么您可能需要重新考虑您的设计。

        • 将您的方法拆分为更小、更简单的方法。
        • 使用列表推导和allany 等方法来避免编写显式循环。

        执行其中任何一个都应该意味着您不再有这个问题。

        【讨论】:

        • 我不确定我是否同意这一点,特别是在对复杂数据结构进行迭代的情况下。有时你只是在字典中字典!
        • @karielalex:你不同意这两点,还是只同意第二点?
        • 如果您在一种方法中有三个级别的循环,那么您可能需要重新考虑您的设计。我认为迭代数据结构的情况(在这种情况下,多次迭代在语义上是一个部分,不应该被拆分或修剪)和在一个地方做了太多事情的情况是有区别的.在后一种情况下,我同意你的两个观点。例如,我最近构建了一个 DFA,它有一个转换表 initial node -> arc type -> guard -> final node。要遍历所有边,您需要三个循环!
        • 虽然,阅读这个案例,我认为它可能是后者的一个例子。 for row in b 看起来不太乐观。
        • @katrielalex:我同意你的观点,在某些算法中,一个方法中的三个循环相互内部是有意义的,例如 Floyd-Warshall:en.wikipedia.org/wiki/Floyd%E2%80%93Warshall_algorithm。我怀疑这里是这种情况,但很难从发布的代码中看出。我已经看过一些 OPs 以前的问题,所以我对代码的外观有一个很好的了解,我猜它并不漂亮,最高投票的答案只会让它变得更不漂亮。
        【解决方案7】:

        try/except/raise,正如@gddc 的评论中所建议的,是一种可能性。另一种是将两个嵌套循环“包裹”为一个:

        for row in b:
          for brand in (b for d in drug_input for b in brand_names[d]):
            ...
        

        现在,来自for brand 嵌套循环的break 将返回到for row 外部循环级别。当然,这仅在此处被... 替换的代码不需要看到与当前正在检查的药物绑定的drug 名称时才有效。你是这种情况吗?

        【讨论】:

        • 简单到可以得到所需的药物名称。 for brand, drug in ((b,d) for d in drug_input for b in brand_names[d]):
        【解决方案8】:

        这个使用布尔值来查看你是否完成了:

        done = False
        for x in xs:
            for y in ys:
                if bad:
                    done = True
                    break
        
            if done:
                break
        

        如果没有使用中断,这个将continue。如果有休息,else 将被跳过,因此它将看到下一个 break。这种方法的好处是不必使用变量,但对某些人来说可能更难阅读。

        for x in xs:
            for y in ys:
                if bad:
                    break
            else:
                continue
        
            break
        

        【讨论】:

        • 嗯,它有三个循环,而不是两个。
        • 好吧,我想也许 OP 可以推断出三个循环。
        • @Teodor:阅读 q。小心 - 最外面的循环不需要退出,所以 w/2 循环的例子是正确的
        • 好评论,但指向 for ... else... 结构的指针可能对新手有好处
        【解决方案9】:
        for row in b:
            ok = True
            for drug in drug_input:
                if not ok:
                    break;
                for brand in brand_names[drug]:
                    if not ok:
                        break
                    if whatever:
                        ok = False
        

        【讨论】:

          【解决方案10】:
          for row in b:
             more_drugs = True
             for drug in drug_input:
                for brand in brand_names[drug]:
                    if something:
                        more_drugs = False
                        break
          
                if not more_drugs:
                    break
          

          Python 没有用于同时中断两个循环的控制结构,因此您需要手动执行此类操作。

          【讨论】:

          • @cjrh:我很好奇:为什么你会写“很好的答案”但不投票给答案?没有压力...
          【解决方案11】:

          未经测试:

          inner_termination=False
          for row in b:
              for drug in drug_input:
                 for brand in brand_names[drug]:
                     <blah>
                     if break_condition:
                         inner_termination=True
                         break 
                     <blah>
                 if inner_termination:
                     inner_termination=False
                     break 
          

          【讨论】:

            猜你喜欢
            • 2017-07-30
            • 1970-01-01
            • 2015-08-15
            • 1970-01-01
            • 1970-01-01
            • 2011-10-02
            • 2013-05-15
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多