如果不是Python == vs if!=

时间:2015-06-24 12:35:39

标签: python if-statement equality

这两行代码有什么区别:

if not x == 'val':

if x != 'val':

一个比另一个更有效吗?

使用

会更好吗?
if x == 'val':
    pass
else:

7 个答案:

答案 0 :(得分:215)

使用dis查看为两个版本生成的字节码:

<强> not ==

  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   

后者的操作较少,因此可能稍微提高效率。

有人指出in the commments(谢谢,@Quincunx)你所拥有的if foo != barif 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

<强> !=

  2           0 LOAD_FAST                0 (foo)
              3 LOAD_FAST                1 (bar)
              6 COMPARE_OP               3 (!=)
              9 POP_JUMP_IF_FALSE       16

在这种情况下,除非每次比较所需的工作量有所不同,否则您根本不会看到任何性能差异。

但请注意,两个版本在逻辑上并不总是相同,因为它取决于相关对象的__eq____ne__的实现。每the data model documentation

  

比较运营商之间没有隐含的关系。该   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 != ynot x == y 更具可读性。

答案 1 :(得分:29)

@jonrsharpe对正在发生的事情有一个很好的解释。我想我只是显示了运行10,000个次数的3个选项中的每一个的时间差异(足以显示略有差异)。

使用的代码:

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分析器结果:

enter image description here

因此,我们可以看到if not x == 'val':if x != 'val':之间的差异非常小,约为0.7%。其中,if x != 'val':是最快的。

然而,最令人惊讶的是,我们可以看到

if x == 'val':
        pass
    else:

实际上是最快的,并且比if x != 'val':低约0.3%。这不是很易读,但我想如果你想要一个可以忽略不计的性能改进,那么可以沿着这条路走下去。

答案 2 :(得分:6)

在第一个Python中,必须执行一个不必要的操作(而不仅仅是检查不等于它必须检查它是否相等,因此再操作一次)。从一次执行中区分出来是不可能的,但是如果多次运行,第二次执行会更有效率。总的来说,我会使用第二个,但数学上它们是相同的

答案 3 :(得分:5)

>>> 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

您可以在此处看到not x == y的指令多于x != y。因此,除非您进行数百万次比较,否则在大多数情况下性能差异将非常小,即使这样也可能不会成为瓶颈的原因。

答案 4 :(得分:5)

另外请注意,因为其他答案大多正确地回答了您的问题,如果某个班级仅定义__eq__()而非__ne__(),那么您的COMPARE_OP (!=)将会__eq__()否定它。那时候,你的第三种选择可能会更有效率,但只有在你需要速度时才应该考虑,因为它很难快速理解。

答案 5 :(得分:3)

关于你的阅读方式。 not运算符是动态的,这就是您能够在

中应用它的原因
if not x == 'val':

!=可以在更好的上下文中作为运算符来读取,而==Disposable相反。

答案 6 :(得分:1)

我想扩展上面的可读性评论。

同样,我完全同意可读性覆盖其他(性能无关紧要)问题。

我想指出的是,大脑解释“积极”的速度要快于“消极”。例如,“停止”与“不要去”(由于单词数量不同,这是一个相当糟糕的例子)。

所以给出了一个选择:

if a == b
    (do this)
else
    (do that)

优于功能等同的:

if a != b
    (do that)
else
    (do this)

可读性/可理解性较差会导致更多错误。也许不是在初始编码中,而是(不像你那么聪明!)维护改变......