¿Python `si x no es Ninguno` o `si no x es Ninguno`? [cerrado]
Siempre pensé que la if not x is None
versión era más clara, pero tanto la guía de estilo de Google como PEP-8 usanif x is not None
. ¿Existen diferencias menores de rendimiento (supongo que no) y hay algún caso en el que una realmente no encaja (lo que convierte al otro en un claro ganador para mi convención)?*
*Me refiero a cualquier singleton, en lugar de solo None
.
...para comparar singletons como Ninguno. El uso es o no es.
No hay diferencia de rendimiento, ya que se compilan con el mismo código de bytes:
>>> import dis
>>> dis.dis("not x is None")
1 0 LOAD_NAME 0 (x)
2 LOAD_CONST 0 (None)
4 COMPARE_OP 9 (is not)
6 RETURN_VALUE
>>> dis.dis("x is not None")
1 0 LOAD_NAME 0 (x)
2 LOAD_CONST 0 (None)
4 COMPARE_OP 9 (is not)
6 RETURN_VALUE
Estilísticamente, trato de evitar not x is y
que un lector humano pueda malinterpretarlo como (not x) is y
. Si escribo x is not y
entonces no hay ambigüedad.
La guía de estilo de Google y Python es la mejor práctica:
if x is not None:
# Do something about x
Su uso not x
puede provocar resultados no deseados.
Vea abajo:
>>> x = 1
>>> not x
False
>>> x = [1]
>>> not x
False
>>> x = 0
>>> not x
True
>>> x = [0] # You don't want to fall in this one.
>>> not x
False
Quizás le interese ver en qué literales se evalúan True
o False
en Python:
- Prueba de valor de verdad
Editar para comentar a continuación:
Acabo de hacer algunas pruebas más. not x is None
no niega x
primero y luego se compara con None
. De hecho, parece que el is
operador tiene mayor prioridad cuando se usa de esa manera:
>>> x
[0]
>>> not x is None
True
>>> not (x is None)
True
>>> (not x) is None
False
Por lo tanto, not x is None
en mi sincera opinión, es mejor evitarlo.
Más edición:
Acabo de hacer más pruebas y puedo confirmar que el comentario de bukzor es correcto. (Al menos no pude demostrar lo contrario).
Este medio if x is not None
tiene el resultado exacto como if not x is None
. Me corrijo. Gracias bukzor.
Sin embargo, mi respuesta sigue siendo válida: utilice el convencionalif x is not None
.:]
El código debe escribirse para que sea comprensible para el programador en primer lugar y, en segundo lugar, para el compilador o intérprete. El constructo "no es" se parece más al inglés que "no es".
Pitón
if x is not None
oif not x is None
?
TLDR: el compilador de código de bytes los analiza a ambos x is not None
, por lo que, en aras de la legibilidad, utilice 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 por encima del rendimiento.
Python optimiza la legibilidad, especialmente en este contexto.
Analizar y compilar el código de bytes
The not
se une más débilmente que is
, por lo que aquí no hay una diferencia lógica. Ver la documentación :
Los operadores
is
yis not
prueban la identidad del objeto:x is y
es verdadero si y sólo si xey son el mismo objeto.x is not y
produce el valor de verdad inverso.
Esto is not
está previsto específicamente en la gramática de Python como una mejora de la legibilidad del lenguaje:
comp_op: '<'|'>'|'=='|'>='|'<='|'<>'|'!='|'in'|'not' 'in'|'is'|'is' 'not'
Por eso es también 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 luego el compilador de bytes realmente traducirá el not ... is
archivo a 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
Por lo tanto, en aras de la legibilidad y del uso del lenguaje previsto, utilice is not
.
No usarlo no es prudente.