while(1)与while(True)——为什么会有差异(在python 2字节码中)?
对perl中关于无限循环的这个问题很感兴趣,我决定在python中运行类似的比较。我希望编译器会为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("-------
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