这两行代码的区别是什么:
if not x == 'val':
and
if x != 'val':
一个比另一个更有效率吗?
用它会更好吗
if x == 'val':
pass
else:
这两行代码的区别是什么:
if not x == 'val':
and
if x != 'val':
一个比另一个更有效率吗?
用它会更好吗
if x == 'val':
pass
else:
当前回答
@jonrsharpe对正在发生的事情有一个很好的解释。我认为我只需要在运行3个选项10,000,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)
和cProfile分析器的结果:
因此,我们可以看到if not x == 'val':和if x != 'val':之间有0.7%的微小差异。其中,如果x != 'val':是最快的。 然而,最令人惊讶的是,我们可以看到 如果x == 'val': 通过 其他: 实际上是最快的,并且比x != 'val':快~0.3%。这不是很好读,但我想如果您想要微不足道的性能改进,可以采用这种方法。
其他回答
在第一个操作中,Python必须执行一个不必要的操作(而不是仅仅检查不等于,它必须检查它是否等于,因此多一个操作)。从一次执行中不可能看出区别,但如果运行多次,第二次将更有效。总的来说,我会用第二个,但从数学上讲,它们是一样的
我想对上面的可读性评论进行扩展。
同样,我完全同意可读性高于其他(性能无关紧要的)问题。
我想指出的是,大脑解释“积极”的速度比解释“消极”的速度快。例如,"stop"和。“do not go”(这是一个相当糟糕的例子,因为两个词的数量不同)。
如果有一个选择:
if a == b
(do this)
else
(do that)
比功能等效的更可取:
if a != b
(do that)
else
(do this)
可读性/可理解性越低,bug就越多。也许不是在最初的编码中,但是(不像你那么聪明!)维护更改…
使用dis查看为两个版本生成的字节码:
不= =
4 0 LOAD_FAST 0 (foo)
3 LOAD_FAST 1 (bar)
6 COMPARE_OP 2 (==)
9 UNARY_NOT
10 RETURN_VALUE
!=
4 0 LOAD_FAST 0 (foo)
3 LOAD_FAST 1 (bar)
6 COMPARE_OP 3 (!=)
9 RETURN_VALUE
后者的操作更少,因此效率可能略高。
有人在评论中指出(谢谢,@Quincunx),如果foo != bar vs.如果不foo == bar,操作的数量是完全相同的,只是COMPARE_OP发生了变化,POP_JUMP_IF_TRUE切换到POP_JUMP_IF_FALSE:
不是= =:
2 0 LOAD_FAST 0 (foo)
3 LOAD_FAST 1 (bar)
6 COMPARE_OP 2 (==)
9 POP_JUMP_IF_TRUE 16
!=
2 0 LOAD_FAST 0 (foo)
3 LOAD_FAST 1 (bar)
6 COMPARE_OP 3 (!=)
9 POP_JUMP_IF_FALSE 16
在这种情况下,除非每次比较所需的工作量有所不同,否则不太可能看到任何性能差异。
但是,请注意,这两个版本在逻辑上并不总是相同的,因为它将依赖于问题对象的__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
最后,也许是最重要的:一般来说,当两者在逻辑上相同时,x != y比不x == y更具可读性。
>>> 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
这里你可以看到不是x == y比x != y多一条指令。所以在大多数情况下,性能差异将是非常小的,除非你做了数百万个比较,即使这样,这也不太可能是瓶颈的原因。
关键在于你的阅读方式。不是算子是动态的,这就是为什么你可以把它应用到
if not x == 'val':
但是!=可以在更好的上下文中被理解为一个与==功能相反的操作符。