繁体   English   中英

Python if not == vs if !=

[英]Python if not == vs if !=

这两行代码有什么区别:

if not x == 'val':

if x != 'val':

一种比另一种更有效吗?

使用会更好吗

if x == 'val':
    pass
else:

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

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


有人指出, 在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

!=

  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 != ynot x == y更具可读性

@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% 的微小差异。 其中, if x != 'val':是最快的。

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

if x == 'val':
        pass
    else:

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

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

另外要注意的是,由于其他答案大部分正确地回答了您的问题,如果一个类只定义了__eq__()而不是__ne__() ,那么您的COMPARE_OP (!=)将运行__eq__()并否定它。 那时,您的第三种选择可能会更有效一点,但只有在您需要速度时才应考虑,因为很难快速理解。

>>> 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 == yx != y多一条指令。 因此,除非您进行数百万次比较,否则在大多数情况下性能差异将非常小,即便如此,这也可能不会成为瓶颈的原因。

这是关于你的阅读方式。 not运算符是动态的,这就是为什么您可以将其应用于

if not x == 'val':

但是!=可以在更好的上下文中被理解为一个运算符,它的作用与==作用相反。

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

同样,我完全同意可读性优先于其他(性能无关紧要的)问题。

我想指出的是,大脑对“积极”的解释比对“消极”的解释更快。 例如,“停止”与“不要走”(由于字数不同,这是一个相当糟糕的例子)。

所以给出一个选择:

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

比功能等效的更可取:

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM