【问题标题】:What's the difference between "while 1" and "while True"?“while 1”和“while True”有什么区别?
【发布时间】:2011-01-16 17:55:42
【问题描述】:

我见过两种在 Python 中创建无限循环的方法:

  1. while 1:
        do_something()
    
  2. while True:
        do_something()
    

这些有什么区别吗?一个比另一个更蟒蛇?

【问题讨论】:

  • 也许一个无限循环不是pythonic? (见 balpha)

标签: python while-loop infinite-loop


【解决方案1】:

我认为这主要是风格问题。两者都应该很容易理解为无限循环。

但是,我个人更喜欢第二种选择。那是因为它只需要一个心理上的微步就可以理解,尤其是对于没有 C 背景的程序员。

【讨论】:

    【解决方案2】:

    第一个也适用于True 尚未定义的早期版本。

    【讨论】:

    • 此时,一旦您为 Python 3 编程,无论如何保持向后兼容性几乎没有意义。
    • 我想知道最后一个不支持 True 的 Python 版本是什么?
    【解决方案3】:

    这只是风格问题,任何编程初学者都可以理解。

    但第二个选项只有在 True 没有分配给 False 时才有效,这在 Python 3 之前是可能的:

    >>> True = False
    >>> True
    False
    

    【讨论】:

    • 这是一个很好的观察,但是任何与其他开发人员在项目中这样做的人几乎肯定会被打到他们生命的一英寸之内......
    【解决方案4】:

    IMO 的第二个选项更明显

    如果您可以摆脱 while 并编写更紧凑的代码,那可能会更 Pythonic。
    例如:

    # Get the even numbers in the range 1..10
    # Version 1
    l = []
    n = 1
    while 1:
        if n % 2 == 0: l.append(n)
        n += 1
        if n > 10: break
    print l
    
    # Version 2
    print [i for i in range(1, 11) if i % 2 == 0]
    
    # Version 3
    print range(2, 11, 2)
    

    【讨论】:

      【解决方案5】:

      如果您有一个假设在有限时间内终止的算法,我会推荐这个,它总是比while True 更安全:

      maxiter = 1000
      for i in xrange(maxiter):
         # your code
         # on success:
           break
      else:
         # that algorithm has not finished in maxiter steps! do something accordingly
      

      【讨论】:

      • 我在这方面不同意,并且有一个著名的学校可以使标准尽可能清晰。如果您期望一个值为零,那么说“== 0”并且不要依赖“
      【解决方案6】:

      最pythonic的方式总是最易读的。使用while True:

      【讨论】:

      • "while 1:" 与 "for(;;)" 完全不同 :-)
      • @nomemory:问题是关于“Pythonic”——这与 C 程序员几乎没有关系。如果你想要 C 程序员可读的东西,请使用 C。
      • @S.Lott :我想说的是可读性是非常相对的。
      【解决方案7】:

      我相信第二个表达式更明确,因此更多 pythonic

      【讨论】:

        【解决方案8】:

        都没有。

        它们都意味着我必须扫描代码以查找break,而不是能够在它所属的位置看到停止条件。

        我尽量避免这种事情,如果不可能,让代码自己说话:

        while not found_answer:
            check_number += 1
            if check_number == 42:
                found_answer = True
        

        编辑:上面的“避免”这个词似乎不够清楚。使用基本上无限循环并将​​其从循环内的某个位置(使用break通常应该完全避免。有时这是不可能的。在这种情况下,我喜欢使用类似于上面代码的东西,然而,它仍然代表相同的概念——上面的代码只不过是一种妥协——但在至少,我可以在开头显示循环的目的——就像我不会调用函数do_something_with_args(*args)

        【讨论】:

        • 但是在你的代码中,你只需要扫描found_answer = True的代码。
        • 我不明白这有多可取。通常使用break 的原因是停止条件不能容易或有效地表达。如果您的字面意思是使用像found_answer 这样的变量,那么您必须扫描它而不是break - 通常您仍然需要continue 而不是break 才能使其退出循环。
        • @Mike Graham:是的,我说过我想完全避免这种情况。如果我使用它,我会尝试通过给布尔值一个名称来说明是什么使循环停止的原因。
        • @Scott Griffiths:但与Truenot found_answernot received_quit_command 不同,它向代码的读者传达了一些信息。
        • @balpha:这是一个公平的观点,但我不禁觉得你正在引入一个新变量并添加额外的条件评估只是为了让循环的意图更清晰,当你真的需要在开头写一个简单的注释吗?
        【解决方案9】:

        更好的方法是“while True”,有条件地跳出循环。

        【讨论】:

          【解决方案10】:

          基本上没关系,这些细节并不会真正影响某事物是否是“pythonic”。

          但是,如果您对琐事感兴趣,则存在一些差异。

          1. builtin boolean type didn't exist till Python 2.3 所以打算在古代版本上运行的代码倾向于使用while 1: 形式。例如,您会在标准库中看到它。

          2. True 和 False 内置函数是 not reserved words prior to Python 3,因此可以分配给它们,改变它们的值。这有助于解决上述情况,因为代码可以执行 True = 1 以实现向后兼容性,但这意味着名称 True 每次使用时都需要在全局字典中查找。

          3. 由于上述限制,两个版本编译成的字节码在 Python 2 中是不同的,因为它对不能用于True 的常量整数进行了优化。因为 Python 在编译 1 时可以判断它始终为非零,所以它移除了条件跳转并且根本不加载常量:

            >>> import dis
            >>> def while_1():
            ...     while 1:
            ...         pass
            ...
            >>> def while_true():
            ...     while True:
            ...         pass
            ...
            >>> dis.dis(while_1)
              2           0 SETUP_LOOP               5 (to 8)
            
              3     >>    3 JUMP_ABSOLUTE            3
                          6 POP_TOP
                          7 POP_BLOCK
                    >>    8 LOAD_CONST               0 (None)
                         11 RETURN_VALUE
            >>> dis.dis(while_true)
              2           0 SETUP_LOOP              12 (to 15)
                    >>    3 LOAD_GLOBAL              0 (True)
                          6 JUMP_IF_FALSE            4 (to 13)
                          9 POP_TOP
            
              3          10 JUMP_ABSOLUTE            3
                    >>   13 POP_TOP
                         14 POP_BLOCK
                    >>   15 LOAD_CONST               0 (None)
                         18 RETURN_VALUE
            

          所以,while True: 更易于阅读,while 1: 对旧版本的 Python 更友好一些。由于这些天您不太可能需要在 Python 2.2 上运行,或者不需要担心循环的字节码计数,因此前者略胜一筹。

          【讨论】:

          • 我想指出,以我的拙见,做某事的最 Pythonic 方式是不要担心这样的细节。虽然这篇文章绝对有趣且内容丰富,我也很欣赏这一点,但我坚持认为while True: 更符合 Python 风格。至少我解释奇怪的术语 pythonic 的方式,你的里程可能会有所不同。
          • 刚刚尝试做True = False,“按预期”工作,有趣:)
          • 如果你真的很努力,你仍然可以在 3.x 中重新定义True。在 3.0 中,import builtins; builtins.__dict__['True'] = 0 会这样做;在 3.3 中,您必须获得更多创意,但这仍然是可能的。如果最坏的情况变得最糟,您总是可以ctypes 进入 C API(或其他实现的等效项)。有趣的是,编译器假定你不能这样做,所以一些表达式会被编译出来,而另一些会以一种依赖于实现/版本的方式使用你的新值。如果你能找到所有这些的好用处......你可能会找到更好的方式来利用你的时间......
          【解决方案11】:

          这并不重要。两者都不难阅读或理解,尽管我个人总是使用while True,这更明确一些。

          更一般地说,人们用 Python 编写的大量 while-break 循环可能是别的东西。有时我看到有人写i = 0; while True: i += 1 ...,可以用for i in itertools.count()代替,有人写while True: foo = fun() if foo is None: break,而这可以写for foo in iter(fun, None),这需要学习,但样板和犯傻错误的机会较少。

          【讨论】:

            猜你喜欢
            • 2023-03-14
            • 2011-04-18
            • 2014-05-19
            • 1970-01-01
            • 2013-10-29
            • 2019-10-07
            • 1970-01-01
            • 2013-04-10
            • 1970-01-01
            相关资源
            最近更新 更多