while 1: do_something()
这两者有区别吗?哪一个更符合Pythonic的风格?while True: do_something()
while 1:
do_something()
while True:
do_something()
这两者有区别吗?哪一个更符合Pythonic的风格?基本上并不重要,这些细节并不会影响某个东西是否“Pythonic”。
但是,如果您对琐事感兴趣,那么有一些区别。
内置布尔类型直到 Python 2.3 才存在,因此旨在运行在古老版本的代码往往使用 while 1:
形式。例如,在标准库中就可以看到这种形式的代码。
在 Python 3 之前,True 和 False 这两个关键字 不是保留字,因此可以被赋值,改变它们的值。这有助于上面的情况,因为代码可以使用 True = 1
实现向后兼容性,但意味着每次使用名称 True
都需要在全局字典中查找。
由于上述限制,两个版本编译的字节码在 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上运行或担心循环的字节码计数,前者略微更优。True
。在3.0中,import builtins; builtins.__dict__['True'] = 0
就可以了;在3.3中,你需要更有创意,但仍然是可能的。如果情况变得最糟,你总可以通过ctypes
进入C API(或其他实现的等效方式)。有趣的是编译器“假定”你不能这样做,因此某些表达式将被编译掉,而其他表达式将以一种依赖于实现/版本的方式使用你的新值。如果你能找到一个好用途……你可能会找到更好的利用时间的方法…… - abarnertwhile 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
,而无法在代码所在的位置看到停止条件。
我尽可能避免这种情况的发生,如果无法避免,则让代码自己说明:
while not found_answer:
check_number += 1
if check_number == 42:
found_answer = True
编辑: 看起来上面提到的“避免”这个词并不够清晰。使用基本上是无限循环并在循环内的某个地方离开它(使用break
) 通常应该完全避免。有时候那是不可能的。在这种情况下,我喜欢使用像上面的代码一样的东西,然而,它仍然代表着相同的概念 - 上面的代码只不过是一个妥协 - 但至少,我可以在开始时就展示循环的目的 – 就像我不会把一个函数称为do_something_with_args(*args)
。
found_answer = True
这行代码就行了。 - Mike GrahamTrue
不同,not found_answer
或not received_quit_command
向代码读者传达了一些信息。 - balpha在我看来,第二个选项更加明显。
如果你能够摆脱 while 循环并写出更加紧凑的代码,那可能会更符合 Python 的风格。
例如:
# 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)
我认为这主要是一个风格问题。两种方式都应该能够轻松理解为无限循环。
然而,个人更喜欢第二个选项。这是因为它只需要少量的心理步骤来理解,特别是对于没有C语言背景的程序员。
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