Python if not == vs if !=

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/31026754/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 09:20:45  来源:igfitidea点击:

Python if not == vs if !=

pythonif-statementequality

提问by lafferc

What is the difference between these two lines of code:

这两行代码有什么区别:

if not x == 'val':

and

if x != 'val':

Is one more efficient than the other?

一种比另一种更有效吗?

Would it be better to use

使用会更好吗

if x == 'val':
    pass
else:

采纳答案by jonrsharpe

Using disto look at the bytecode generated for the two versions:

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

not ==

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   

The latter has fewer operations, and is therefore likely to be slightly more efficient.

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



It was pointed out in the commments(thanks, @Quincunx) that where you have if foo != barvs. if not foo == barthe number of operations is exactly the same, it's just that the COMPARE_OPchanges and POP_JUMP_IF_TRUEswitches to POP_JUMP_IF_FALSE:

有人指出,在commments(感谢,@Quincunx)说,你必须if foo != barif not foo == bar操作的数量是完全一样的,它只是在COMPARE_OP改变和POP_JUMP_IF_TRUE切换到POP_JUMP_IF_FALSE

not ==:

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

In this case, unless there was a difference in the amount of work required for each comparison, it's unlikely you'd see any performance difference at all.

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



However, note that the two versions won't always be logically identical, as it will depend on the implementations of __eq__and __ne__for the objects in question. Per the data model documentation:

但是,请注意,这两个版本在逻辑上并不总是相同,因为这取决于相关对象的实现__eq____ne__相关对象的实现。根据数据模型文档

There are no implied relationships among the comparison operators. The truth of x==ydoes not imply that x!=yis false.

比较运算符之间没有隐含的关系。的真理x==y并不意味着那x!=y是错误的。

For example:

例如:

>>> class Dummy(object):
    def __eq__(self, other):
        return True
    def __ne__(self, other):
        return True


>>> not Dummy() == Dummy()
False
>>> Dummy() != Dummy()
True


Finally, and perhaps most importantly: in general, where the two arelogically identical, x != yis much more readable than not x == y.

最后,也许是最重要的:一般来说,当两者逻辑上相同时,x != ynot x == y.

回答by JediPythonClone

In the first one Python has to execute one more operations than necessary(instead of just checking not equal to it has to check if it is not true that it is equal, thus one more operation). It would be impossible to tell the difference from one execution, but if run many times, the second would be more efficient. Overall I would use the second one, but mathematically they are the same

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

回答by kylie.a

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

Here you can see that not x == yhas one more instruction than x != y. So the performance difference will be very small in most cases unless you are doing millions of comparisons and even then this will likely not be the cause of a bottleneck.

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

回答by Himanshu Mishra

It's about your way of reading it. notoperator is dynamic, that's why you are able to apply it in

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

if not x == 'val':

But !=could be read in a better context as an operator which does the opposite of what ==does.

但是!=可以在更好的上下文中将其理解为与操作相反的操作符==

回答by Red Shift

@jonrsharpe has an excellent explanation of what's going on. I thought I'd just show the difference in time when running each of the 3 options 10,000,000 times (enough for a slight difference to show).

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

Code used:

使用的代码:

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)

And the cProfile profiler results:

和 cProfile 分析器结果:

enter image description here

在此处输入图片说明

So we can see that there is a very minute difference of ~0.7% between if not x == 'val':and if x != 'val':. Of these, if x != 'val':is the fastest.

所以我们可以看到if not x == 'val':和之间有大约 0.7% 的微小差异if x != 'val':。其中,if x != 'val':是最快的。

However, most surprisingly, we can see that

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

if x == 'val':
        pass
    else:

is in fact the fastest, and beats if x != 'val':by ~0.3%. This isn't very readable, but I guess if you wanted a negligible performance improvement, one could go down this route.

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

回答by Jacob Zimmerman

An additional note, since the other answers answered your question mostly correctly, is that if a class only defines __eq__()and not __ne__(), then your COMPARE_OP (!=)will run __eq__()and negate it. At that time, your third option is likely to be a tiny bit more efficient, but should only be considered if you NEED the speed, since it's difficult to understand quickly.

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

回答by Alan Jay Weiner

I want to expand on my readability comment above.

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

Again, I completely agree with readability overriding other (performance-insignificant) concerns.

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

What I would like to point out is the brain interprets "positive" faster than it does "negative". E.g., "stop" vs. "do not go" (a rather lousy example due to the difference in number of words).

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

So given a choice:

所以给出一个选择:

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

is preferable to the functionally-equivalent:

比功能等效的更可取:

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

Less readability/understandability leads to more bugs. Perhaps not in initial coding, but the (not as smart as you!) maintenance changes...

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