while (1) vs. while(True) -- 为什么有区别(在python 2字节码中)?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3815359/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 12:52:15  来源:igfitidea点击:

while (1) vs. while(True) -- Why is there a difference (in python 2 bytecode)?

python

提问by AndrewF

Intrigued by this question about infinite loops in perl: while (1) Vs. for (;;) Is there a speed difference?, I decided to run a similar comparison in python. I expected that the compiler would generate the same byte code for while(True): passand while(1): pass, but this is actually not the case in python2.7.

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

The following script:

以下脚本:

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)

produces the following results:

产生以下结果:

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        

Using while Trueis noticeably more complicated. Why is this?

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

In other contexts, python acts as though Trueequals 1:

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

>>> True == 1
True

>>> True + True
2

Why does whiledistinguish the two?

为什么要while区分两者?

I noticed that python3 does evaluate the statements using identical operations:

我注意到 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         

Is there a change in python3 to the way booleans are evaluated?

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

采纳答案by kennytm

In Python 2.x, Trueis not a keyword, but just a built-in global constantthat is defined to 1 in the booltype. Therefore the interpreter still has to load the contents of True. In other words, Trueis reassignable:

在 Python 2.x 中,True不是关键字,而只是在类型中定义为 1的内置全局常量bool。因此解释器仍然需要加载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


In Python 3.x it truly becomes a keywordand a real constant:

在 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

thus the interpreter can replace the while True:loop with an infinite loop.

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

回答by Aaron Hall

This isn't quite right,

这不太对,

thus the interpreter can replace the while True: loop with an infinite loop.

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

as one can still break out of the loop. But it is true that such a loop's elseclause would never be accessed in Python 3. And it is also true that simplifying the value lookup makes it run just as quickly as while 1in Python 2.

因为仍然可以跳出循环。但确实,else在 Python 3 中永远不会访问这样的循环子句。而且简化值查找使其运行速度与while 1在 Python 2 中一样快也是正确的。

Performance Comparison

性能比较

Demonstrating the difference in time for a somewhat nontrivial while loop:

演示一个有点不平凡的 while 循环的时间差异:

Setup

设置

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

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

Python 2

蟒蛇 2

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

Python 3

蟒蛇 3

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

Explanation

解释

To explain the difference, in Python 2:

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

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

but in Python 3:

但在 Python 3 中:

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

Since Trueis a keyword in Python 3, the interpreter doesn't have to look up the value to see if someone replaced it with some other value. But since one can assign Trueto another value, the interpreter has to look it up every time.

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

Conclusion for Python 2

Python 2 的结论

If you have a tight, long-running loop in Python 2, you probably should use while 1:instead of while True:.

如果您在Python 2有一紧,长时间运行的循环,你应该使用while 1:代替while True:

Conclusion for Python 3

Python 3 的结论

Use while True:if you have no condition for breaking out of your loop.

while True:如果您没有跳出循环的条件,请使用。

回答by abarnert

This is a 7-year-old question that already has a great answer, but a misconception in the question, which isn't addressed in any of the answers, makes it potentially confusing for some of the other questions marked as duplicates.

这是一个已经有 7 年历史的问题,已经有了很好的答案,但该问题中的一个误解,在任何答案中都没有解决,这使得其他一些标记为重复的问题可能会造成混淆。

In other contexts, python acts as though True equals 1:

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

>>> True == 1
True

>>> True + True
2

Why does while distinguish the two?

为什么while要区分两者?

In fact, whileisn't doing anything different here at all. It distinguishes 1and Truein exactly the same way that the +example does.

事实上,while在这里根本没有做任何不同的事情。它区分1,并True以完全同样的方式,+例如做。



Here's 2.7:

这是 2.7:

>>> dis.dis('True == 1')
  1           0 LOAD_GLOBAL              0 (True)
              3 LOAD_CONST               1 (1)
              6 COMPARE_OP               2 (==)
              9 RETURN_VALUE

>>> dis.dis('True == 1')
  1           0 LOAD_GLOBAL              0 (True)
              3 LOAD_GLOBAL              0 (True)
              6 BINARY_ADD
              9 RETURN_VALUE

Now compare:

现在比较:

>>> dis.dis('1 + 1')
  1           0 LOAD_CONST               1 (2)
              3 RETURN_VALUE

It's emitting a LOAD_GLOBAL (True)for each True, and there's nothing the optimizer can do with a global. So, whiledistinguishes 1and Truefor the exact same reason that +does. (And ==doesn't distinguish them because the optimizer doesn't optimize out comparisons.)

LOAD_GLOBAL (True)为 each发出 a ,True优化器无法对全局进行任何操作。因此,while区分1并且True出于完全相同的原因+。(并且==不区分它们,因为优化器不会优化比较。)



Now compare 3.6:

现在比较 3.6:

>>> dis.dis('True == 1')
  1           0 LOAD_CONST               0 (True)
              2 LOAD_CONST               1 (1)
              4 COMPARE_OP               2 (==)
              6 RETURN_VALUE

>>> dis.dis('True + True')
  1           0 LOAD_CONST               1 (2)
              2 RETURN_VALUE

Here, it's emitting a LOAD_CONST (True)for the keyword, which the optimizer cantake advantage of. So, True + 1doesn'tdistinguish, for exactly the same reason while Truedoesn't. (And ==still doesn't distinguish them because the optimizer doesn't optimize out comparisons.)

在这里,它LOAD_CONST (True)为关键字发出 a ,优化器可以利用它。所以,True + 1区分,因为完全相同的原因while True不区分。(并且==仍然没有区分它们,因为优化器不会优化比较。)



Meanwhile, if the code isn't optimized out, the interpreter ends up treating Trueand 1exactly the same in all three of these cases. boolis a subclass of int, and inherits most of its methods from int, and Truehas an internal integer value of 1. So, whether you're doing a whiletest (__bool__in 3.x, __nonzero__in 2.x), a comparison (__eq__), or arithmetic (__add__), you're calling the same method whether you use Trueor 1.

同时,如果代码没有优化出来,解释器最终会在所有这三种情况下处理True1完全相同。bool是 的子类int,从 继承其大部分方法int,并且True内部整数值为 1。因此,无论您是在进行while测试(__bool__在 3.x 中,__nonzero__在 2.x 中)、比较 ( __eq__) 还是算术( __add__) ,无论您使用True还是,您都在调用相同的方法1