Python if x is not None
ou if not x is None
?
TLDR: O compilador de bytecode analisa os dois para x is not None
- portanto, para facilitar a leitura, use if x is not None
.
Legibilidade
Usamos o Python porque valorizamos coisas como legibilidade humana, usabilidade e correção de vários paradigmas de programação sobre desempenho.
O Python otimiza a legibilidade, especialmente neste contexto.
Analisando e compilando o bytecode
Os not
vínculos são mais fracos que is
, portanto, não há diferença lógica aqui. Veja a documentação :
Os operadores is
e is not
testam a identidade do objeto: x is y
é verdadeira se e somente se xey são o mesmo objeto. x is not y
produz o valor inverso da verdade.
O is not
é especificamente fornecido na gramática Python como uma melhoria de legibilidade para a linguagem:
comp_op: '<'|'>'|'=='|'>='|'<='|'<>'|'!='|'in'|'not' 'in'|'is'|'is' 'not'
E, portanto, também é um elemento unitário da gramática.
Obviamente, não é analisado da mesma forma:
>>> 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())]))"
Mas o compilador de bytes converterá realmente o not ... is
para 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
Portanto, para facilitar a leitura e usar o idioma como pretendido, use is not
.
Para não usá-lo, não é sábio.
is not
é um operador por si só. Like!=
. Se você preferirnot x is None
, também deve preferirnot a == b
terminara != b
.