Python `if x is not None` or `if not x is None`?
我一直认为
*我指的是任何单件的,而不仅仅是
...to compare singletons like
None. Use is or is not.
没有性能差异,因为它们编译到相同的字节码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | 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 |
在风格上,我尽量避免使用
谷歌和Python的风格指南都是最佳实践:
1 2 | if x is not None: # Do something about x |
使用
1 2 3 4 5 6 7 8 9 10 11 12 | >>> 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中对
- 真值检验
编辑以下评论:
我只是做了更多的测试。
1 2 3 4 5 6 7 8 | >>> x [0] >>> not x is None True >>> not (x is None) True >>> (not x) is None False |
因此,在我看来,以东十一〔三〕是公正的,最好避免。
更多编辑:
我只是做了更多的测试,可以确认Bukzor的评论是正确的。(至少,我无法证明这一点。)
这意味着
然而,我的回答仍然是:使用传统的
代码应该首先被编写成程序员可以理解的,其次是编译器或解释器。"is not"结构比"not is"更像英语。
答案比人们想象的要简单。
这两种方法都没有技术优势,"x不是y"是其他人都使用的,这使得它成为了一个明确的赢家。不管它是否"看起来更像英语",每个人都会使用它,这意味着Python的每一个用户——甚至中国的用户,他们的语言Python看起来一点也不像——都会一目了然地理解它,在这里,稍微不常见的语法需要几个额外的大脑周期来解析。
不要为了与众不同而与众不同,至少在这个领域是这样。
Python
if x is not None orif not x is None ?
tldr:字节码编译器将它们都解析为
我们使用python是因为我们重视人的可读性、可用性和各种编程范例的正确性,而不是性能。
python针对可读性进行了优化,特别是在这个上下文中。
解析和编译字节码The operators
is andis not test for object identity:x is y is true
if and only if x and y are the same object.x is not y yields the
inverse truth value.
在python语法中,为了提高语言的可读性,专门提供了
1 | comp_op: '<'|'>'|'=='|'>='|'<='|'<>'|'!='|'in'|'not' 'in'|'is'|'is' 'not' |
所以它也是语法的一个单一元素。
当然,它的解析方式不同:
1 2 3 4 5 | >>> 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())]))" |
但是,字节编译器实际上会将
1 2 3 4 5 6 7 8 9 10 11 | >>> 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 |
因此,为了可读性和按预期使用语言,请使用
不使用它是不明智的。
由于文体原因,与否定
如果存在性能差异,我的钱就花在EDOCX1上了(18),但这几乎肯定不是决定更喜欢这种技术的动机。它显然依赖于实现。由于
我个人用
1 | if not (x is None): |
每个程序员,甚至那些不精通Python语法的程序员,都能立即理解它,而不会产生歧义。
也就是说,这对我来说更像是一种偏好。
我更喜欢更易读的形式
试试这个:
1 2 | if x != None: # do stuff with x |