897

我一直认为if not x is None版本更清晰,但谷歌的风格指南PEP-8都使用if x is not None. 是否存在任何细微的性能差异(我假设没有),是否有任何情况下一个真的不适合(使另一个明显成为我的大会的赢家)?*

*我指的是任何单身人士,而不仅仅是None.

...比较像 None 这样的单例。使用是或不是。

4

9 回答 9

1174

没有性能差异,因为它们编译为相同的字节码:

>>> import dis
>>> dis.dis("not x is None")
  1           0 LOAD_NAME                0 (x)
              2 LOAD_CONST               0 (None)
              4 COMPARE_OP               9 (is not)
              6 RETURN_VALUE
>>> dis.dis("x is not None")
  1           0 LOAD_NAME                0 (x)
              2 LOAD_CONST               0 (None)
              4 COMPARE_OP               9 (is not)
              6 RETURN_VALUE

在风格上,我尽量避免not x is y,人类读者可能会将其误解为(not x) is y. 如果我写x is not y,那么就没有歧义。

于 2010-04-26T03:55:04.673 回答
333

Google 和Python的风格指南都是最佳实践:

if x is not None:
    # Do something about x

使用not x会导致不需要的结果。

见下文:

>>> x = 1
>>> not x
False
>>> x = [1]
>>> not x
False
>>> x = 0
>>> not x
True
>>> x = [0]         # You don't want to fall in this one.
>>> not x
False

您可能有兴趣了解在 PythonTrue中评估哪些文字:False


编辑以下评论:

我只是做了一些更多的测试。not x is None不会x先否定,然后与None. 实际上,以is这种方式使用运算符似乎具有更高的优先级:

>>> x
[0]
>>> not x is None
True
>>> not (x is None)
True
>>> (not x) is None
False

因此,not x is None在我看来,最好避免。


更多编辑:

我只是做了更多的测试,可以确认 bukzor 的评论是正确的。(至少,我无法以其他方式证明这一点。)

这意味着if x is not None准确的结果为if not x is None。我站得更正了。谢谢布克佐。

但是,我的回答仍然成立:使用传统的if x is not None.:]

于 2010-04-26T03:13:32.220 回答
138

代码应该首先被程序员理解,然后是编译器或解释器。“不是”结构比“不是”更接近英语。

于 2010-04-26T03:15:55.180 回答
38

蟒蛇if x is not Noneif not x is None

TLDR:字节码编译器将它们都解析为x is not None- 因此为了便于阅读,请使用if x is not None.

可读性

我们使用 Python 是因为我们看重诸如人类可读性、可用性和各种编程范式的正确性之类的东西,而不是性能。

Python 优化了可读性,尤其是在这种情况下。

解析和编译字节码

的结合比not is,所以这里没有逻辑上的区别。请参阅文档

对象身份的运算符is和测试:当且仅当 x 和 y 是同一个对象时为真。产生逆真值。is notx is yx is not y

在Python语法is not中专门提供了 ,作为语言的可读性改进:

comp_op: '<'|'>'|'=='|'>='|'<='|'<>'|'!='|'in'|'not' 'in'|'is'|'is' 'not'

所以它也是语法的一个单一元素。

当然,解析不一样:

>>> import ast
>>> ast.dump(ast.parse('x is not None').body[0].value)
"Compare(left=Name(id='x', ctx=Load()), ops=[IsNot()], comparators=[Name(id='None', ctx=Load())])"
>>> ast.dump(ast.parse('not x is None').body[0].value)
"UnaryOp(op=Not(), operand=Compare(left=Name(id='x', ctx=Load()), ops=[Is()], comparators=[Name(id='None', ctx=Load())]))"

但是随后字节编译器实际上会将其转换not ... isis not

>>> import dis
>>> dis.dis(lambda x, y: x is not y)
  1           0 LOAD_FAST                0 (x)
              3 LOAD_FAST                1 (y)
              6 COMPARE_OP               9 (is not)
              9 RETURN_VALUE
>>> dis.dis(lambda x, y: not x is y)
  1           0 LOAD_FAST                0 (x)
              3 LOAD_FAST                1 (y)
              6 COMPARE_OP               9 (is not)
              9 RETURN_VALUE

因此,为了便于阅读并按预期使用语言,请使用is not.

不使用它不明智的。

于 2015-07-20T16:18:17.683 回答
32

答案比人们想象的要简单。

无论哪种方式都没有技术优势,而且“x is not y”是其他人使用的,这使它成为明显的赢家。它是否“看起来更像英语”并不重要;每个人都在使用它,这意味着 Python 的每个用户——即使是中国用户,其语言 Python 看起来一点也不像——都会一眼就理解它,其中稍微不常见的语法将需要几个额外的大脑周期来解析。

不要仅仅为了与众不同而与众不同,至少在这个领域是这样。

于 2010-04-26T07:18:03.083 回答
15

就个人而言,我使用

if not (x is None):

每个程序员都可以毫不含糊地立即理解这一点,即使是那些不熟悉 Python 语法的人。

于 2016-06-26T16:14:23.827 回答
11

出于文体原因,is not运算符优于否定结果。is" if x is not None:" 读起来像英文,但 " if not x is None:" 需要理解运算符优先级,读起来不像英文。

如果存在性能差异,我的钱就在上面is not,但这几乎肯定不是决定更喜欢该技术的动机。它显然是依赖于实现的。由于is不可覆盖,因此无论如何优化任何区别都应该很容易。

于 2010-04-26T04:32:34.880 回答
2

if not x is None与其他编程语言更相似,但if x is not None对我来说绝对听起来更清晰(并且在英语语法上更正确)。

也就是说,这对我来说似乎更像是一种偏好。

于 2010-04-26T03:14:29.227 回答
1

我更喜欢可读性更强的形式x is not y ,而不是我想的如何最终编写运算符的代码处理优先级以生成更具可读性的代码。

于 2015-09-24T07:19:34.627 回答