laf*_*erc 175 python if-statement equality
这两行代码有什么区别:
if not x == 'val':
Run Code Online (Sandbox Code Playgroud)
和
if x != 'val':
Run Code Online (Sandbox Code Playgroud)
一个比另一个更有效吗?
使用会更好吗?
if x == 'val':
pass
else:
Run Code Online (Sandbox Code Playgroud)
jon*_*rpe 221
使用dis
一下两个版本生成的字节码:
not ==
4 0 LOAD_FAST 0 (foo)
3 LOAD_FAST 1 (bar)
6 COMPARE_OP 2 (==)
9 UNARY_NOT
10 RETURN_VALUE
Run Code Online (Sandbox Code Playgroud)
!=
4 0 LOAD_FAST 0 (foo)
3 LOAD_FAST 1 (bar)
6 COMPARE_OP 3 (!=)
9 RETURN_VALUE
Run Code Online (Sandbox Code Playgroud)
后者的操作较少,因此可能稍微提高效率.
有人指出,在commments(感谢,@Quincunx)说,你必须if foo != bar
对if not foo == bar
操作的数量是完全一样的,它只是在COMPARE_OP
改变和POP_JUMP_IF_TRUE
切换到POP_JUMP_IF_FALSE
:
not ==
:
2 0 LOAD_FAST 0 (foo)
3 LOAD_FAST 1 (bar)
6 COMPARE_OP 2 (==)
9 POP_JUMP_IF_TRUE 16
Run Code Online (Sandbox Code Playgroud)
!=
2 0 LOAD_FAST 0 (foo)
3 LOAD_FAST 1 (bar)
6 COMPARE_OP 3 (!=)
9 POP_JUMP_IF_FALSE 16
Run Code Online (Sandbox Code Playgroud)
在这种情况下,除非每次比较所需的工作量存在差异,否则您根本不会看到任何性能差异.
但请注意,这两个版本在逻辑上并不总是相同,因为它将取决于所讨论对象的实现__eq__
和__ne__
.根据数据模型文档:
比较运算符之间没有隐含的关系.事实
x==y
并非暗示这x!=y
是错误的.
例如:
>>> class Dummy(object):
def __eq__(self, other):
return True
def __ne__(self, other):
return True
>>> not Dummy() == Dummy()
False
>>> Dummy() != Dummy()
True
Run Code Online (Sandbox Code Playgroud)
最后,也许最重要的是:一般来说,两者在逻辑上相同,x != y
比可读性更强not x == y
.
Red*_*ift 29
@jonrsharpe对正在发生的事情有一个很好的解释.我想我只是在运行10,000个选项中的每个选项时显示时间上的差异(足以显示略有差异).
使用的代码:
def a(x):
if x != 'val':
pass
def b(x):
if not x == 'val':
pass
def c(x):
if x == 'val':
pass
else:
pass
x = 1
for i in range(10000000):
a(x)
b(x)
c(x)
Run Code Online (Sandbox Code Playgroud)
并且cProfile分析器结果如下:
所以我们可以看到,if not x == 'val':
和之间的差异很小,约为0.7%if x != 'val':
.其中,if x != 'val':
是最快的.
然而,最令人惊讶的是,我们可以看到
if x == 'val':
pass
else:
Run Code Online (Sandbox Code Playgroud)
实际上是最快的,并且if x != 'val':
减少了~0.3%.这不是很易读,但我想如果你想要一个可以忽略不计的性能改进,那么可以沿着这条路走下去.
在第一个Python中,必须执行一个不必要的操作(而不仅仅是检查不等于它必须检查它是否相等,因此还有一个操作).从一次执行中区分出来是不可能的,但是如果多次运行,第二次执行会更有效率.总的来说,我会使用第二个,但在数学上它们是相同的
>>> from dis import dis
>>> dis(compile('not 10 == 20', '', 'exec'))
1 0 LOAD_CONST 0 (10)
3 LOAD_CONST 1 (20)
6 COMPARE_OP 2 (==)
9 UNARY_NOT
10 POP_TOP
11 LOAD_CONST 2 (None)
14 RETURN_VALUE
>>> dis(compile('10 != 20', '', 'exec'))
1 0 LOAD_CONST 0 (10)
3 LOAD_CONST 1 (20)
6 COMPARE_OP 3 (!=)
9 POP_TOP
10 LOAD_CONST 2 (None)
13 RETURN_VALUE
Run Code Online (Sandbox Code Playgroud)
在这里你可以看到not x == y
还有一个指令x != y
.因此,除非您进行数百万次比较,否则在大多数情况下性能差异将非常小,即使这样也可能不会成为瓶颈的原因.
另外一个注释,因为其他答案大多正确地回答了你的问题,如果一个类只定义__eq__()
而不是__ne__()
,那么你的COMPARE_OP (!=)
意志就会运行__eq__()
并否定它.那时候,你的第三种选择可能会更有效率,但只有在你需要速度时才应考虑,因为很难快速理解.