25

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

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

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

4

11 回答 11

47

从根本上说没关系,这些细节并不会真正影响某些东西是否是“pythonic”。

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

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

  2. True 和 False 内置不是 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 上运行,或者需要担心循环的字节码计数,因此前者略胜一筹。

于 2010-02-14T18:08:33.043 回答
11

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

于 2010-02-14T17:47:32.923 回答
5

这并不重要。两者都很难阅读或理解,尽管我个人总是使用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),这需要学习,但样板代码和犯愚蠢错误的机会较少。

于 2010-02-14T18:22:55.773 回答
4

两者都不。

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

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

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

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

于 2010-02-14T17:57:32.743 回答
3

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)
于 2010-02-14T17:45:46.083 回答
2

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

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

于 2010-02-14T17:36:13.873 回答
2

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

于 2010-02-14T17:37:34.730 回答
2

如果您有一个假设在有限时间内终止的算法,我会推荐这个,它总是比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
于 2010-02-14T17:46:17.203 回答
1

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

于 2010-02-14T17:51:16.847 回答
0

这只是风格问题,任何编程初学者都会理解这两种选择。

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

>>> True = False
>>> True
False
于 2010-02-14T17:40:32.537 回答
0

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

于 2010-02-14T17:59:11.257 回答