2017-04-17 55 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