Python 如果不是 == 与如果 !=
Python if not == vs if !=
这两行代码有什么区别:
if not x == 'val':
和
if x != 'val':
一个比另一个更有效率吗?
用
会不会更好
if x == 'val':
pass
else:
在第一个中,Python 必须多执行一个操作(而不是仅仅检查不等于,它必须检查它是否不等于,因此多执行一个操作).不可能分辨出一次执行的区别,但如果 运行 多次,则第二次执行会更有效率。总的来说我会使用第二个,但在数学上它们是相同的
使用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
后者的操作较少,因此效率可能会稍高一些。
有人指出 (thanks, @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__
的实现有问题的对象。每 the data model documentation:
There are no implied relationships among the comparison operators. The
truth of x==y
does not imply that x!=y
is false.
例如:
>>> class Dummy(object):
def __eq__(self, other):
return True
def __ne__(self, other):
return True
>>> not Dummy() == Dummy()
False
>>> Dummy() != Dummy()
True
最后,也许也是最重要的一点:一般来说,两个 在逻辑上是相同的,x != y
比 [=30] 更具可读性=].
>>> 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
多了一条指令。因此,在大多数情况下,性能差异将非常小,除非您进行数百万次比较,即便如此,这也可能不是瓶颈的原因。
这是关于你的阅读方式。 not
运算符是动态的,这就是为什么您可以在
中应用它
if not x == 'val':
但是 !=
可以在更好的上下文中理解为运算符,它与 ==
的作用相反。
@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%。这不是很可读,但我想如果你想要微不足道的性能改进,可以沿着这条路走。
另外请注意,由于其他答案大多正确回答了您的问题,如果 class 仅定义 __eq__()
而不是 __ne__()
,那么您的 COMPARE_OP (!=)
will 运行 __eq__()
并否定它。届时,您的第三个选项可能会更有效一点,但只有在您需要速度时才应考虑,因为它很难快速理解。
我想扩展我上面的可读性评论。
同样,我完全同意可读性高于其他(性能无关紧要的)问题。
我想指出的是大脑解释 "positive" 比 "negative" 快。例如,"stop" 与 "do not go"(由于字数不同,这是一个相当糟糕的例子)。
所以给一个选择:
if a == b
(do this)
else
(do that)
优于功能等效的:
if a != b
(do that)
else
(do this)
更少 readability/understandability 会导致更多错误。也许不是在最初的编码中,而是(不像你那么聪明!)维护变化......
这两行代码有什么区别:
if not x == 'val':
和
if x != 'val':
一个比另一个更有效率吗?
用
会不会更好if x == 'val':
pass
else:
在第一个中,Python 必须多执行一个操作(而不是仅仅检查不等于,它必须检查它是否不等于,因此多执行一个操作).不可能分辨出一次执行的区别,但如果 运行 多次,则第二次执行会更有效率。总的来说我会使用第二个,但在数学上它们是相同的
使用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
后者的操作较少,因此效率可能会稍高一些。
有人指出 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__
的实现有问题的对象。每 the data model documentation:
There are no implied relationships among the comparison operators. The truth of
x==y
does not imply thatx!=y
is false.
例如:
>>> class Dummy(object):
def __eq__(self, other):
return True
def __ne__(self, other):
return True
>>> not Dummy() == Dummy()
False
>>> Dummy() != Dummy()
True
最后,也许也是最重要的一点:一般来说,两个 在逻辑上是相同的,x != y
比 [=30] 更具可读性=].
>>> 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
多了一条指令。因此,在大多数情况下,性能差异将非常小,除非您进行数百万次比较,即便如此,这也可能不是瓶颈的原因。
这是关于你的阅读方式。 not
运算符是动态的,这就是为什么您可以在
if not x == 'val':
但是 !=
可以在更好的上下文中理解为运算符,它与 ==
的作用相反。
@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%。这不是很可读,但我想如果你想要微不足道的性能改进,可以沿着这条路走。
另外请注意,由于其他答案大多正确回答了您的问题,如果 class 仅定义 __eq__()
而不是 __ne__()
,那么您的 COMPARE_OP (!=)
will 运行 __eq__()
并否定它。届时,您的第三个选项可能会更有效一点,但只有在您需要速度时才应考虑,因为它很难快速理解。
我想扩展我上面的可读性评论。
同样,我完全同意可读性高于其他(性能无关紧要的)问题。
我想指出的是大脑解释 "positive" 比 "negative" 快。例如,"stop" 与 "do not go"(由于字数不同,这是一个相当糟糕的例子)。
所以给一个选择:
if a == b
(do this)
else
(do that)
优于功能等效的:
if a != b
(do that)
else
(do this)
更少 readability/understandability 会导致更多错误。也许不是在最初的编码中,而是(不像你那么聪明!)维护变化......