while (1) 与 while(True) —— 为什么会有区别(在 python 2 字节码中)?

新手上路,请多包涵

对这个关于 perl 中的无限循环的问题很感兴趣: while (1) Vs. for (;;) 有速度差异吗? ,我决定在 python 中运行类似的比较。我预计编译器会为 while(True): passwhile(1): pass 生成相同的字节码,但实际上在 python2.7 中并非如此。

以下脚本:

 import dis

def while_one():
    while 1:
        pass

def while_true():
    while True:
        pass

print("while 1")
print("----------------------------")
dis.dis(while_one)

print("while True")
print("----------------------------")
dis.dis(while_true)

产生以下结果:

 while 1
----------------------------
  4           0 SETUP_LOOP               3 (to 6)

  5     >>    3 JUMP_ABSOLUTE            3
        >>    6 LOAD_CONST               0 (None)
              9 RETURN_VALUE
while True
----------------------------
  8           0 SETUP_LOOP              12 (to 15)
        >>    3 LOAD_GLOBAL              0 (True)
              6 JUMP_IF_FALSE            4 (to 13)
              9 POP_TOP

  9          10 JUMP_ABSOLUTE            3
        >>   13 POP_TOP
             14 POP_BLOCK
        >>   15 LOAD_CONST               0 (None)
             18 RETURN_VALUE

使用 while True 明显更复杂。为什么是这样?

在其他情况下,python 就像 True 等于 1:

 >>> True == 1
True

>>> True + True
2

为什么 while 区分这两者?

我注意到 python3 确实使用相同的操作评估语句:

 while 1
----------------------------
  4           0 SETUP_LOOP               3 (to 6)

  5     >>    3 JUMP_ABSOLUTE            3
        >>    6 LOAD_CONST               0 (None)
              9 RETURN_VALUE
while True
----------------------------
  8           0 SETUP_LOOP               3 (to 6)

  9     >>    3 JUMP_ABSOLUTE            3
        >>    6 LOAD_CONST               0 (None)
              9 RETURN_VALUE

python3 对布尔值的评估方式有变化吗?

原文由 AndrewF 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.1k
2 个回答

在 Python 2.x 中, True 不是关键字,而只是在 bool 类型中定义为 1 的 内置全局常量。因此,解释器仍然必须加载 True 的内容。换句话说, True 是可重新分配的:

 Python 2.7 (r27:82508, Jul  3 2010, 21:12:11)
[GCC 4.0.1 (Apple Inc. build 5493)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> True = 4
>>> True
4


在 Python 3.x 中,它真正成为一个关键字 和一个真正的常量:

 Python 3.1.2 (r312:79147, Jul 19 2010, 21:03:37)
[GCC 4.2.1 (Apple Inc. build 5664)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> True = 4
  File "<stdin>", line 1
SyntaxError: assignment to keyword

因此,解释器可以用无限循环替换 while True: 循环。

原文由 kennytm 发布,翻译遵循 CC BY-SA 3.0 许可协议

称其为“无限循环”并不完全正确

因此解释器可以用无限循环替换 while True: 循环。

因为仍然可以跳出这样一个 while True: 循环。但是这样一个循环的 else 子句永远不会在 Python 3 中被访问。

Python 3 简化了 True 的值查找,使其运行速度与 Python 2 中的 while 1 一样快。

性能比较

演示一个有点重要的 while 循环的时间差异:

设置

def while1():
    x = 0
    while 1:
        x += 1
        if x == 10:
            break

def whileTrue():
    x = 0
    while True:
        x += 1
        if x == 10:
            break

蟒蛇2

 >>> import timeit
>>> min(timeit.repeat(while1))
0.49712109565734863
>>> min(timeit.repeat(whileTrue))
0.756627082824707

蟒蛇3

 >>> import timeit
>>> min(timeit.repeat(while1))
0.6462970309949014
>>> min(timeit.repeat(whileTrue))
0.6450748789939098

解释

为了解释差异,在 Python 2 中:

 >>> import keyword
>>> 'True' in keyword.kwlist
False

但在 Python 3 中:

 >>> import keyword
>>> 'True' in keyword.kwlist
True
>>> True = 'true?'
  File "<stdin>", line 1
SyntaxError: can't assign to keyword

由于 True 是 Python 3 中的关键字,解释器不必查找该值以查看是否有人将其替换为其他值。但是由于可以将 True 分配给 Python 2 中的另一个值,解释器每次都必须查找它。

Python 2 的结论

如果您在 Python 2 中有一个紧密的、长时间运行的循环,您可能应该使用 while 1: 而不是 while True:

Python 3 的结论

使用 while True: 如果你没有条件打破你的循环。

原文由 Russia Must Remove Putin 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
logo
Stack Overflow 翻译
子站问答
访问
宣传栏