2017-04-17 41 views
2

以前的开发已经离开代码中的一个很奇怪的not x is None尤达条件:与尤达条件“没x是无”

>>> 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?或者前者总是等于后者?

+0

这都是关于运算符的优先级。阅读这个答案http:// stackoverflow。com/questions/31421379/why-does-not-true-false-false-true-return-false/31458009#31458009 – Kasramvd

+0

是按照[文档](https://docs.python.org/3/reference/expressions。 html#operator-precedence),** not **的优先级低于compare **的是**。所以你以前的假设应该是正确的。 – umutto

+0

“Yoda条件”将是'None is x'。 – Ryan

回答

2

由于is具有比not优先级数字,则该表达式是等效的:

万一x = Nonex is None的计算结果为True,并not x is None评估为False 万一x = 1x is None的计算结果为False,并not x is None评估为True

如果x = Nonex is not None评估为False 如果x = 1x is not None评估为True

因此,即使这些动作在语法上不等效,但结果是等效的。

这是not x is None的AST:

enter image description here

这是x is not None的AST:

enter image description here

如第二个图中可以看出,内节点是比较节点,因此在not之前评估x is None

关于表达式的实际评估,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 
0

is not是(我相信,唯一的)在Python两关键字操作,和x is not y是完全等效于not x is yid(x) != id(y)也会返回相同的结果。最佳读者理解标准拼写为x is not y

+2

'不在'是另一个。 – Ryan

+0

这就是为什么我尽量避免对我的信仰过于夸张 - 通常有人会更好地通知或更聪明来纠正我。谢谢! – holdenweb