Python`如果x不是None`或`if not x is None`?

时间:2010-04-26 03:10:30

标签: python coding-style boolean-expression

我一直认为if not x is None版本更清晰,但Google的style guidePEP-8都使用if x is not None。是否有任何轻微的性能差异(我假设没有),并且是否有任何一个真正不合适的情况(使另一个成为我的会议的明显赢家)?*

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

  

...比较单身人士   没有。使用是否。

10 个答案:

答案 0 :(得分:875)

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

Python 2.6.2 (r262:71600, Apr 15 2009, 07:20:39)
>>> import dis
>>> def f(x):
...    return x is not None
...
>>> dis.dis(f)
  2           0 LOAD_FAST                0 (x)
              3 LOAD_CONST               0 (None)
              6 COMPARE_OP               9 (is not)
              9 RETURN_VALUE
>>> def g(x):
...   return not x is None
...
>>> dis.dis(g)
  2           0 LOAD_FAST                0 (x)
              3 LOAD_CONST               0 (None)
              6 COMPARE_OP               9 (is not)
              9 RETURN_VALUE

在风格上,我尽量避免使用not x is y。尽管编译器总是将其视为not (x is y),但人类读者可能会误解构造为(not x) is y。如果我写x is not y,那就没有歧义。

答案 1 :(得分:152)

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

您可能有兴趣在Python中查看哪些文字被评估为TrueFalse

编辑以下评论:

我刚做了一些测试。 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。我纠正了。谢谢bukzor。

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

答案 2 :(得分:119)

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

答案 3 :(得分:29)

答案比人们做的简单。

无论哪种方式都没有技术优势,“x不是y”是其他人使用的,这使它成为明显的赢家。它“看起来更像英语”并不重要;每个人都使用它,这意味着Python的每个用户 - 甚至是中文用户,他们的语言Python看起来都不像 - 会一目了然地理解它,其中稍微不那么常见的语法将花费几个额外的脑循环来解析。

不要只是为了与众不同,至少在这个领域是不同的。

答案 4 :(得分:23)

  

Python if x is not Noneif not x is None

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

可读性

我们使用Python是因为我们重视人的可读性,可用性以及各种编程范式的正确性。

Python优化了可读性,尤其是在此上下文中。

解析和编译字节码

not binds more weaklyis,所以这里没有逻辑差异。请参阅documentation

  

运算符isis not测试对象标识:x is y为真   当且仅当x和y是同一个对象时。 x is not y产生了   反向真值。

is not专门为Python grammar提供了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 ... is

但是字节编译器实际上会将is 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

因此,为了便于阅读和使用预期的语言,请使用module.exports = function (one, two, callback) { var fs = require("fs"); var path = require("path"); var konc = "." + two; fs.readdir(one, function (err, list) { if (err) return callback(err); var list = list.filter(function (x) { return path.extname(x) == konc; }); callback(null, list) }) }

不使用 不是 明智。

答案 5 :(得分:9)

由于样式原因,is not运算符优先于否定is的结果。 “if x is not None:”的读取方式与英语类似,但“if not x is None:”需要了解运算符优先级,并且不会像英语一样阅读。

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

答案 6 :(得分:6)

就个人而言,我使用

if not (x is None):
每个程序员都会毫不含糊地理解

,即使是那些不熟悉Python语法的程序员。

答案 7 :(得分:1)

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

那说对我来说这似乎更像是一种偏爱。

答案 8 :(得分:0)

我更喜欢更易读的形式x is not y 我认为如何最终编写运算符的代码处理优先级,以产生更易读的代码。

答案 9 :(得分:-4)

试试这个:

    if x != None:
       # do stuff with x