Yoda 条件 "not x is None"

Yoda condition with "not x is None"

之前的开发者在代码中留下了一个非常奇怪的not x is None yoda 条件:

>>> x = None
>>> not x is None
False
>>> x = 1
>>> not x is None
True

经过一些测试,我的输出似乎与 x is not None 相同。

>>> x = None
>>> not x is None
False
>>> x is not None
False
>>> x = 1
>>> not x is None
True
>>> x is not None
True

not x is None 是否总是等同于 x is not None

把条件分解一下,not (x is None)还是(not x) is None?或者前者总是等同于后者?

因为is的优先级高于not,所以表达式是等价的:

如果x = Nonex is None 的计算结果为 Truenot x is None 的计算结果为 False 如果 x = 1x is None 的计算结果为 Falsenot x is None 的计算结果为 True

如果x = Nonex is not None 的计算结果为 False 如果 x = 1x is not None 的计算结果为 True

因此,即使操作在语法上不等价,结果也是等价的。

这是 not x is None 的 AST:

这是 x is not None 的 AST:

从第二张图中可以看出,内部节点是比较节点,因此x is Nonenot之前被评估。

关于表达式的实际计算,python 似乎为两者创建了相同的字节码。在这个例子中可以看出:

def foo(x):
    x is not None


def bar(x):
    not x is None

import dis
dis.dis(foo)
dis.dis(bar)

两者都生成:

      0 LOAD_FAST                0 (x)
      3 LOAD_CONST               0 (None)
      6 COMPARE_OP               9 (is not)
      9 POP_TOP             
     10 LOAD_CONST               0 (None)
     13 RETURN_VALUE 

is not 是(我相信,唯一的)Python 中的双关键字运算符,而 x is not y 完全等同于 not x is yid(x) != id(y) 也会返回相同的结果。最佳 reader 理解的规范拼写为 x is not y.