【问题标题】:Else clause on Python while statementPython while 语句中的 Else 子句
【发布时间】:2011-03-18 18:41:32
【问题描述】:

我注意到以下代码在 Python 中是合法的。我的问题是为什么?有什么具体原因吗?

n = 5
while n != 0:
    print n
    n -= 1
else:
    print "what the..."

【问题讨论】:

  • @detly:那是因为大多数人都避免这种结构。 :) 我相信 Guido 在 Py3k 过程中提到,至少,为此使用选择 else 这个词是一个非常糟糕的主意,他们不会再做这些了。
  • @Nicholas Knight - 是的,虽然很诱人,但可能只有我乍一看就明白了。任何其他可怜的 sap 都必须去查看语言规范,或者及时返回并在 Sta-heeeeey 上发布问题......
  • 选择 'else' 背后的想法是,这个结构通常与 while 循环内的 'if X: break' 一起使用。由于如果我们不跳出循环,就会执行“else”子句,因此它与“if”形成了一种“else”。
  • 他们应该将其重命名为after:
  • @naught101 - After 也不太合适,因为如果您使用“break”或“return”退出循环,它将不会执行。我总是告诉那些努力记住用法的人,“如果你要跳出循环,你就有机会在你的 break 语句之前做一些事情。如果你用尽了你的集合(在 for 循环中)或打破你的循环条件(在一个while循环中),'else'子句是你结束的地方。”

标签: python syntax while-loop if-statement


【解决方案1】:

else 子句仅在您的 while 条件变为 false 时执行。如果您 break 退出循环,或者引发异常,则不会执行。

考虑它的一种方法是将其视为关于条件的 if/else 构造:

if condition:
    handle_true()
else:
    handle_false()

类似于循环结构:

while condition:
    handle_true()
else:
    # condition is false now, handle and go on with the rest of the program
    handle_false()

一个例子可能是这样的:

while value < threshold:
    if not process_acceptable_value(value):
        # something went wrong, exit the loop; don't pass go, don't collect 200
        break
    value = update(value)
else:
    # value >= threshold; pass go, collect 200
    handle_threshold_reached()

【讨论】:

  • "只有当你的 while 条件为 false 时才会执行 else 子句。"这里的措辞意味着您的 while 状态从 true 状态变为 false,然后 else 将被执行。但是,如果 while 永远不为真,else 子句仍将被执行。
  • pseudocode 如果我错了,请纠正我,但这与 while {} something 完全相同 除了 something 将是如果您在 while 循环中使用 break,则跳过。
  • 也许最精确的伪代码是:while(True) { if (cond) { handle_true(); } 其他 { handle_false();休息; } }
  • “过不去,不收200”,哈哈,知道这个出处的人都度过了美好的童年
  • 如果 while 循环以 'break' 结束,即使 while 条件变为 false,else 子句也不会执行。例如,在 break 之前将条件更改为 false。
【解决方案2】:

else 子句在您正常退出块时执行,方法是遇到循环条件或从 try 块底部掉下来。如果您将breakreturn 超出块或引发异常,则不会执行。它不仅适用于 while 和 for 循环,还适用于 try 块。

您通常会在通常会提前退出循环的地方找到它,而在循环结束时运行是一个意外/不寻常的情况。例如,如果你在一个列表中循环寻找一个值:

for value in values:
    if value == 5:
        print "Found it!"
        break
else:
    print "Nowhere to be found. :-("

【讨论】:

  • 实际上是一个相当有用的结构。不知道我在循环的开头放了多少次found_it=False,然后在结尾对found_it 做一个if 检查
【解决方案3】:

回复Is there a specific reason?,这是一个有趣的应用:打破多层次的循环。

它是这样工作的:外部循环在最后有一个中断,所以它只会执行一次。但是,如果内部循环完成(没有找到除数),那么它会到达 else 语句并且永远不会到达外部 break。这样一来,内部循环中的中断将中断两个循环,而不仅仅是一个循环。

for k in [2, 3, 5, 7, 11, 13, 17, 25]:
    for m in range(2, 10):
        if k == m:
            continue
        print 'trying %s %% %s' % (k, m)
        if k % m == 0:
            print 'found a divisor: %d %% %d; breaking out of loop' % (k, m)
            break
    else:
        continue
    print 'breaking another level of loop'
    break
else:
    print 'no divisor could be found!'

对于whilefor 循环,else 语句在最后执行,除非使用了break

在大多数情况下,有更好的方法来做到这一点(将其包装到函数中或引发异常),但这是可行的!

【讨论】:

  • 我没有投反对票,但我想我知道为什么有人这么做了。你没有回答这个问题,你提供了 14 行代码,只有 2 行描述。如果您提出的问题与您没有告诉我们有关...
  • @BlueEel 感谢您的反馈!我添加了关于代码的更多解释,并更清楚地说明了它是如何回答问题的(因为它确实回答了部分问题)。
  • 您设法将代码置于上下文中,尽管您没有回答所有问题,但我现在看到了相关性。我赞成你的回答,因为它现在对新手和新手有用(就像我自己在 python 方面一样)。 - 谢谢,我学到了一些东西。
  • 我喜欢这个简单的应用程序——现在我明白为什么有人会使用它了。虽然我从未见过需要它。
  • 该示例显示了 for /else 的使用,但问题具体是关于 while /else。
【解决方案4】:

当 while 条件评估为 false 时执行 else 子句。

来自documentation

while 语句用于重复执行,只要表达式为真:

while_stmt ::=  "while" expression ":" suite
                ["else" ":" suite]

这会重复测试表达式,如果为真,则执行第一个套件;如果表达式为假(可能是第一次测试),则执行 else 子句套件(如果存在)并终止循环。

在第一个套件中执行的 break 语句会终止循环而不执行 else 子句的套件。在第一个套件中执行的 continue 语句会跳过套件的其余部分并返回测试表达式。

【讨论】:

    【解决方案5】:

    我的答案将集中在我们何时可以使用 while/for-else。

    乍一看,使用时似乎没有什么不同

    while CONDITION:
        EXPRESSIONS
    print 'ELSE'
    print 'The next statement'
    

    while CONDITION:
        EXPRESSIONS
    else:
        print 'ELSE'
    print 'The next statement'
    

    因为print 'ELSE' 语句似乎总是在两种情况下都执行(无论是在while 循环完成还是未运行时)。

    那么,只有当print 'ELSE'语句不被执行时不同。 就是while下的代码块里面有一个break

    In [17]: i = 0
    
    In [18]: while i < 5:
        print i
        if i == 2:
            break
        i = i +1
    else:
        print 'ELSE'
    print 'The next statement'
       ....:
    0
    1
    2
    The next statement
    

    如果不同:

    In [19]: i = 0
    
    In [20]: while i < 5:
        print i
        if i == 2:
            break
        i = i +1
    print 'ELSE'
    print 'The next statement'
       ....:
    0
    1
    2
    ELSE
    The next statement
    

    return 不在此类别中,因为它对上述两种情况的效果相同。

    异常引发也不会造成差异,因为当它引发时,下一个代码将在异常处理程序(块除外)中执行,else 子句中或while 子句之后的代码不会执行。

    【讨论】:

      【解决方案6】:

      else 子句仅在 while 条件 变为 false 时执行。

      这里有一些例子:

      示例1:最初条件为假,所以执行else-clause

      i = 99999999
      
      while i < 5:
          print(i)
          i += 1
      else:
          print('this')
      

      输出:

      this
      

      示例 2:while 条件 i &lt; 5 从未变为 false,因为 i == 3 打破了循环,所以 else-clause 是未执行。

      i = 0
      
      while i < 5:
          print(i)
          if i == 3:
              break
          i += 1
      else:
          print('this')
      

      输出:

      0
      1
      2
      3
      

      示例 3:i5 时,while 条件 i &lt; 5 变为 false,因此 else-clause 为执行。

      i = 0
      
      while i < 5:
          print(i)
          i += 1
      else:
          print('this')
      

      输出:

      0
      1
      2
      3
      4
      this
      

      【讨论】:

        【解决方案7】:

        我知道这是个老问题,但是……

        正如 Raymond Hettinger 所说,它应该被称为 while/no_break 而不是 while/else
        如果你看这个sn-p,我觉得很容易理解。

        n = 5
        while n > 0:
            print n
            n -= 1
            if n == 2:
                break
        if n == 0:
            print n
        

        现在,我们可以将其与else 交换,而不是在while 循环之后检查条件并摆脱该检查。

        n = 5
        while n > 0:
            print n
            n -= 1
            if n == 2:
                break
        else:  # read it as "no_break"
            print n
        

        我总是把它读成while/no_break 来理解代码,这种语法对我来说更有意义。

        【讨论】:

          【解决方案8】:

          当且仅当 while 循环不再满足其条件时(在您的示例中,当 n != 0 为 false 时)才会执行 else: 语句。

          所以输出是这样的:

          5
          4
          3
          2
          1
          what the...
          

          【讨论】:

          • 我知道,但是这种 while/else 在 Java 中不起作用。当我发现它在 Python 中工作时,我发现它非常有趣。我只是好奇,想知道技术原因。
          • @Ivan:并不是说它在 Java 中不工作,而是它在 Java 中不存在。如果有人愿意将它添加到语言中,它可以工作。
          • 否,而 False: .. else .. 仍然运行 else 子句。更准确的说法是:只有在循环中断时才运行 else。
          • 如果存在return 或引发异常,else 部分也不会运行。
          【解决方案9】:

          如果while循环没有中断,则执行Else。

          我有点喜欢用“跑步者”来比喻。

          “else”就像越过终点线,与您是从赛道的起点还是终点开始无关。 “else”只有在您之间的某个地方中断时才会执行。

          runner_at = 0 # or 10 makes no difference, if unlucky_sector is not 0-10
          unlucky_sector = 6
          while runner_at < 10:
              print("Runner at: ", runner_at)
              if runner_at == unlucky_sector:
                  print("Runner fell and broke his foot. Will not reach finish.")
                  break
              runner_at += 1
          else:
              print("Runner has finished the race!") # Not executed if runner broke his foot.
          

          主要用例是使用这种中断嵌套循环,或者如果您只想在循环没有在某处中断的情况下运行某些语句(认为中断是一种不寻常的情况)。

          例如,下面是一个关于如何在不使用变量或 try/catch 的情况下跳出内部循环的机制:

          for i in [1,2,3]:
              for j in ['a', 'unlucky', 'c']:
                  print(i, j)
                  if j == 'unlucky':
                      break
              else: 
                  continue  # Only executed if inner loop didn't break.
              break         # This is only reached if inner loop 'breaked' out since continue didn't run. 
          
          print("Finished")
          # 1 a
          # 1 b
          # Finished
          

          【讨论】:

            【解决方案10】:

            假设你要在单个链表中搜索元素 x

                def search(self, x):
                    position = 1
                    p =self.start
                    while p is not None:
                        if p.info == x:
                            print(x, " is at position ", position)
                            return True
                        position += 1
                        p = p.link
                    else:
                        print(x, "not found in list") 
                        return False
            

            所以如果条件失败 else 会执行,希望对你有帮助!

            【讨论】:

            • 在此 sn-p 中省略 while 语句的 else: 子句不会改变代码的行为。
            • @BrunoEly这段代码是单链表程序的sn-p,所以需要一整段代码才能准确运行。
            • 你错过了我的意思。我试图在具有 no break 语句while 块之后说 else: 子句是没有意义的——它不会改变代码的行为。
            【解决方案11】:

            在 Python 中更好地使用 'while: else:' 构造应该是如果在 'while' 中没有执行循环,则执行 'else' 语句。它今天的工作方式没有意义,因为您可以使用下面的代码获得相同的结果...

            n = 5
            while n != 0:
                print n
                n -= 1
            print "what the..."
            

            【讨论】:

            • 不,不同之处在于如果您使用breakreturn 关键字离开循环,则不会执行else 块。在您的示例中,如果循环在 break 命令上结束,print 也将被执行。
            • 您描述的是大多数人希望该功能如何发挥作用,而不是它实际上是如何工作的!
            【解决方案12】:

            据我所知,在任何语言的循环中添加 else 的主要原因是迭代器不在您的控制范围内。想象一下,迭代器在服务器上,您只需给它一个信号以获取接下来的 100 条数据记录。只要接收到的数据长度为 100,您就希望循环继续。如果小于,您需要它再循环一次,然后结束它。在许多其他情况下,您无法控制最后一次迭代。在这些情况下可以选择添加 else 让一切变得更容易。

            【讨论】:

            • else: 子句只有在你跳出循环时才会运行,所以这个例子不需要这样的结构。即,else: 块内的任何代码都可能不需要else: 语句(对于此示例)。
            猜你喜欢
            • 2015-04-27
            • 1970-01-01
            • 2021-04-15
            • 2015-11-08
            • 2022-09-23
            • 2015-04-07
            • 2015-11-06
            • 2014-07-01
            • 1970-01-01
            相关资源
            最近更新 更多