关于nonetype:not在Python中没有测试

not None test in Python

本问题已经有最佳答案,请猛点这里访问。

在这些非零测试中。

1
2
3
4
5
if val != None:

if not (val is None):

if val is not None:

哪一个更好,为什么?


1
2
if val is not None:
    # ...

用于测试变量未设置为None的python惯用法。这个习语在用默认参数声明关键字函数的情况下有特殊的用途。is在python中测试身份。因为运行python脚本/程序中只存在一个None实例,所以is是对此的最佳测试。正如JohnsyWeb所指出的,这在PEP8的"规划建议"中进行了讨论。

至于为什么这是首选

1
2
if not (val is None):
    # ...

这只是python禅的一部分:"可读性很重要。"好的python通常接近于好的伪代码。


来自,规划建议,PEP 8:

Comparisons to singletons like None should always be done with
'is' or 'is not', never the equality operators.

Also, beware of writing"if x" when you really mean"if x is not None"
-- e.g. when testing whether a variable or argument that defaults to
None was set to some other value. The other value might have a type
(such as a container) that could be false in a boolean context!

对于任何一个Python程序员来说,PEP8都是必不可少的阅读工具。


后两种类型中的任意一种,因为val可能是定义__eq__()在传递None时返回true的类型。


对于这些类型的问题,最好的选择是准确地了解Python的功能。dis模块提供了难以置信的信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
>>> def f(val):
...   if val != None:
...     return True
...   return False
...
>>> def g(val):
...   if not (val is None):
...     return True
...   return False
...
>>> def h(val):
...   if val is not None:
...     return True
...   return False
...
>>> import dis
>>> dis.dis(f)
  2           0 LOAD_FAST                0 (val)
              3 LOAD_CONST               0 (None)
              6 COMPARE_OP               3 (!=)
              9 POP_JUMP_IF_FALSE       16

  3          12 LOAD_GLOBAL              1 (True)
             15 RETURN_VALUE

  4     >>   16 LOAD_GLOBAL              2 (False)
             19 RETURN_VALUE
>>> dis.dis(g)
  2           0 LOAD_FAST                0 (val)
              3 LOAD_CONST               0 (None)
              6 COMPARE_OP               9 (is not)
              9 POP_JUMP_IF_FALSE       16

  3          12 LOAD_GLOBAL              1 (True)
             15 RETURN_VALUE

  4     >>   16 LOAD_GLOBAL              2 (False)
             19 RETURN_VALUE
>>> dis.dis(h)
  2           0 LOAD_FAST                0 (val)
              3 LOAD_CONST               0 (None)
              6 COMPARE_OP               9 (is not)
              9 POP_JUMP_IF_FALSE       16

  3          12 LOAD_GLOBAL              1 (True)
             15 RETURN_VALUE

  4     >>   16 LOAD_GLOBAL              2 (False)
             19 RETURN_VALUE

注意,最后两种情况简化为相同的操作序列(python读取not (val is None)并使用is not操作符)。第一个使用!=运算符与无运算符进行比较。

正如其他答案所指出的那样,在与无比较时使用!=是一个坏主意。