¿Python `si x no es Ninguno` o `si no x es Ninguno`? [cerrado]

Resuelto orokusaki asked hace 14 años • 9 respuestas

Siempre pensé que la if not x is Noneversió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.

orokusaki avatar Apr 26 '10 10:04 orokusaki
Aceptado

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 yque un lector humano pueda malinterpretarlo como (not x) is y. Si escribo x is not yentonces no hay ambigüedad.

Daniel Stutzbach avatar Apr 26 '2010 03:04 Daniel Stutzbach

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 xpuede 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 Trueo Falseen Python:

  • Prueba de valor de verdad

Editar para comentar a continuación:

Acabo de hacer algunas pruebas más. not x is Noneno niega xprimero y luego se compara con None. De hecho, parece que el isoperador 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 Noneen 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 Nonetiene 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 .:]

Xavier Ho avatar Apr 26 '2010 03:04 Xavier Ho

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".

Mark Ransom avatar Apr 26 '2010 03:04 Mark Ransom

Pitón if x is not Noneo if 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 isy is notprueban la identidad del objeto: x is yes verdadero si y sólo si xey son el mismo objeto. x is not yproduce el valor de verdad inverso.

Esto is notestá 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 ... isarchivo 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.

Russia Must Remove Putin avatar Jul 20 '2015 16:07 Russia Must Remove Putin