The previous dev has left a really strange not x is None
yoda condition in the code:
>>> x = None
>>> not x is None
False
>>> x = 1
>>> not x is None
True
After some testing, I seem the same output as 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
Is not x is None
always equivalent to x is not None
?
To break down the condition, is it not (x is None)
or (not x) is None
? Or will the former always be equivalent to the latter?
Since is
has higher precendence than not
, then the expressions are equivalent:
In case x = None
:
x is None
evaluates to True
, and not x is None
evaluates to False
In case x = 1
:
x is None
evaluates to False
, and not x is None
evaluates to True
In case x = None
:
x is not None
evaluates to False
In case x = 1
:
x is not None
evaluates to True
.
Therefore, even though the actions are not syntactically equivalent, the results are equivalent.
This is the AST of not x is None
:
This is the AST of x is not None
:
As can be seen in the second diagram, the inner node is the compare node, and therefore x is None
is evaluated before the not
.
Regarding actual evaluation of the expression, it seems that python creates the same bytecode for both. It can be seen in this example:
def foo(x):
x is not None
def bar(x):
not x is None
import dis
dis.dis(foo)
dis.dis(bar)
As both generate:
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