关于python:“ while 1”和“ while True”之间有什么区别?

What's the difference between “while 1” and “while True”?

我已经看到了两种在Python中创建无限循环的方法:

  • 1
    2
    while 1:
        do_something()
  • 1
    2
    while True:
        do_something()
  • 这些之间有什么区别吗? 一个比另一个更pythonic吗?


    从根本上讲,这并不重要,这样的细节并不会真正影响某些东西是否为" pythonic"。

    但是,如果您对琐事感兴趣,则有一些区别。

  • 内置的布尔类型直到Python 2.3才存在,因此原本打算在较早版本上运行的代码倾向于使用while 1:形式。例如,您将在标准库中看到它。

  • True和False内置不是Python 3之前的保留字,因此可以分配给它们,以更改其值。这对上述情况有帮助,因为代码可以做到True = 1以实现向后兼容,但是这意味着每次使用全局名称字典时都需要在全局字典中查找名称True

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    >>> 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上运行,也不必担心循环的字节码计数,因此前者在某种程度上是可取的。


    最Python的方式将永远是最易读的。使用while True:


    没关系。两者都不难理解,尽管我个人总是使用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),这需要学习,但需要更少的样板,也没有机会犯傻。


    都不行

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

    我尝试尽可能避免这种情况,如果不可能,请让代码这样说:

    1
    2
    3
    4
    while not found_answer:
        check_number += 1
        if check_number == 42:
            found_answer = True

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


    如果您有一种算法可以在有限时间内终止,那么我建议您这样做,它总是比while True更安全:

    1
    2
    3
    4
    5
    6
    7
    maxiter = 1000
    for i in xrange(maxiter):
       # your code
       # on success:
         break
    else:
       # that algorithm has not finished in maxiter steps! do something accordingly


    IMO的第二种选择更为明显。

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    # 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)


    第一个版本也可以在尚未定义True的早期版本中使用。


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

    但是,我个人更喜欢第二种选择。这是因为它只需要花很少的时间就能理解,特别是对于没有C背景的程序员而言。


    我相信第二个表达式更明确,因此更Python化。


    更好的方法是"有条件时退出循环"时为"真"。


    这只是样式问题,任何编程初学者都可以理解这两种选择。

    但是,第二个选项仅在未将True分配给False的情况下才有效,这在Python 3之前是可行的:

    1
    2
    3
    >>> True = False
    >>> True
    False