Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/289.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
while(1)与while(True)——为什么会有差异(在python 2字节码中)?_Python - Fatal编程技术网

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

while(1)与while(True)——为什么会有差异(在python 2字节码中)?,python,Python,对perl中关于无限循环的这个问题很感兴趣,我决定在python中运行类似的比较。我希望编译器会为while(True):pass和while(1):pass生成相同的字节码,但在python2.7中实际情况并非如此 以下脚本: import dis def while_one(): while 1: pass def while_true(): while True: pass print("while 1") print("-------

对perl中关于无限循环的这个问题很感兴趣,我决定在python中运行类似的比较。我希望编译器会为
while(True):pass
while(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        
使用
而使用True
显然要复杂得多。为什么会这样

在其他上下文中,python的行为就像
True
等于1:

>>> True == 1
True

>>> True + True
2
为什么
将两者区分开来

我注意到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中布尔值的计算方式是否有变化?

在Python2.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

在Python3.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
python3.1.2(r312:791472010年7月19日21:03:37)
[GCC 4.2.1(苹果公司构建5664)]关于达尔文
有关详细信息,请键入“帮助”、“版权”、“信用证”或“许可证”。
>>>真=4
文件“”,第1行
SyntaxError:分配给关键字

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

这不太正确

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

因为你仍然可以打破这个循环。但在Python3中,这样一个循环的
else
子句是绝对不会被访问的。同样,简化值查找可以使其运行速度与Python 2中的
而1
一样快

性能比较 演示一个不太常见的while循环的时间差:

安装程序 Python 2 Python 3 解释 为了解释差异,在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
导入关键字 >>>keyword.kwlist中的“True” 真的 >>>真的 文件“”,第1行 SyntaxError:无法分配给关键字
由于
True
是Python 3中的一个关键字,因此解释器不必查找该值以查看是否有人将其替换为其他值。但是,由于可以将
True
赋值给另一个值,解释器每次都必须查找它

Python 2的结论 如果在Python2中有一个紧凑的、长期运行的循环,那么可能应该使用
while 1:
,而不是
while True:

Python 3的结论
如果你没有条件打破你的循环,那么就使用
,虽然正确:

这是一个7年前的问题,已经有了一个很好的答案,但是问题中的一个误解,没有在任何答案中解决,可能会让其他一些被标记为重复的问题混淆

在其他上下文中,python的行为就像True等于1:

>>> True == 1
True

>>> True + True
2
为什么while会区分这两者

事实上,
while
在这里没有任何不同。它以与
+
示例完全相同的方式区分
1
True


这里是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
现在比较一下:

>>> dis.dis('1 + 1')
  1           0 LOAD_CONST               1 (2)
              3 RETURN_VALUE
对于每个
True
,它都会发出一个
LOAD\u GLOBAL(True)
,而优化器无法处理全局。因此,
while
区分
1
True
,原因与
+
完全相同。(并且,
==
不会区分它们,因为优化器不会优化比较。)


现在比较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
这里,它为关键字发出
LOAD\u CONST(True)
,优化器可以利用它。因此,
True+1
无法区分,原因与
完全相同,而True
无法区分。(并且,
==
仍然无法区分它们,因为优化器没有优化比较。)



同时,如果没有优化代码,解释器最终会在这三种情况下处理
True
1
完全相同
bool
int
的一个子类,它继承了
int
的大部分方法,
True
的内部整数值为1。所以,无论你是在做
测试(
\uuubool\uuuuu
在3.x中,
\uuuu非零
在2.x中),比较(
\uuuu eq\uuuu
),还是算术(
\uu添加
),你都在调用相同的方法,无论你是使用
还是
1
@M.H:AFAIK,将关键字输入到语言中是一种权宜之计。有关一些历史记录,请参阅和。这是否意味着Python 3中的
while 1
while True
是相同的?@StevenM.vascillao是的。可能存在重复的
>>> 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
>>> dis.dis('1 + 1')
  1           0 LOAD_CONST               1 (2)
              3 RETURN_VALUE
>>> 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