Python if x is not Noneo if not x is None?
TLDR: el compilador de bytecode los analiza a ambos, por x is not Nonelo que, por razones de legibilidad, úselos if x is not None.
Legibilidad
Usamos Python porque valoramos cosas como la legibilidad humana, la usabilidad y la corrección de varios paradigmas de programación sobre el rendimiento.
Python optimiza la legibilidad, especialmente en este contexto.
Analizar y compilar el código de bytes
Se not une más débilmente que is, por lo que no hay diferencia lógica aquí. Ver la documentación :
Los operadores isy la is notprueba de identidad del objeto: x is yes verdadero si y solo si x e y son el mismo objeto. x is not yproduce el valor de verdad inverso.
El is notse proporciona específicamente en la gramática de Python como una mejora de legibilidad para el lenguaje:
comp_op: '<'|'>'|'=='|'>='|'<='|'<>'|'!='|'in'|'not' 'in'|'is'|'is' 'not'
Y, por lo tanto, también es un elemento unitario de la gramática.
Por supuesto, no se analiza igual:
>>> import ast
>>> ast.dump(ast.parse('x is not None').body[0].value)
"Compare(left=Name(id='x', ctx=Load()), ops=[IsNot()], comparators=[Name(id='None', ctx=Load())])"
>>> ast.dump(ast.parse('not x is None').body[0].value)
"UnaryOp(op=Not(), operand=Compare(left=Name(id='x', ctx=Load()), ops=[Is()], comparators=[Name(id='None', ctx=Load())]))"
Pero entonces el compilador de bytes realmente traducirá el not ... isa is not:
>>> import dis
>>> dis.dis(lambda x, y: x is not y)
1 0 LOAD_FAST 0 (x)
3 LOAD_FAST 1 (y)
6 COMPARE_OP 9 (is not)
9 RETURN_VALUE
>>> dis.dis(lambda x, y: not x is y)
1 0 LOAD_FAST 0 (x)
3 LOAD_FAST 1 (y)
6 COMPARE_OP 9 (is not)
9 RETURN_VALUE
Entonces, en aras de la legibilidad y el uso del lenguaje como estaba previsto, utilícelo is not.
No usarlo no es sabio.
is notes un operador por derecho propio. Al igual!=. Si lo prefiere,not x is Noneentonces también debería preferirnot a == bmása != b.