proposal how espaƱol enhancement docstrings python coding-style boolean-expression

how - python enhancement proposal no 8 pep8



Python `si x no es ninguno` o` si no x es ninguno`? (10)

Siempre he pensado que la versión if not x is None es más clara, pero la guía de estilo de Google y el PEP-8 usan if x is not None . ¿Hay alguna diferencia de rendimiento menor (supongo que no) y hay algún caso en el que uno realmente no encaja (lo que hace que el otro sea un claro ganador para mi convención)?

* Me estoy refiriendo a cualquier singleton, en lugar de a None .

... para comparar singletons como ninguno. El uso es o no es.


Python if x is not None o if not x is None ?

TLDR: El compilador de bytecode los analiza para que x is not None , por lo que, para mayor facilidad de lectura, use if x is not None .

Legibilidad

Utilizamos Python porque valoramos cosas como la legibilidad humana, la capacidad de uso y la corrección de varios paradigmas de programación sobre el rendimiento.

Python optimiza la legibilidad, especialmente en este contexto.

Analizando y compilando el bytecode

El not une más débilmente de lo que is , por lo que no hay diferencia lógica aquí. Vea la documentation :

Los operadores is y is not prueban la identidad del objeto: x is y es verdadero si y solo si x e y son el mismo objeto. x is not y produce el valor de verdad inverso.

El is not se proporciona específicamente en la grammar Python como una mejora de legibilidad para el lenguaje:

comp_op: ''<''|''>''|''==''|''>=''|''<=''|''<>''|''!=''|''in''|''not'' ''in''|''is''|''is'' ''not''

Y también es un elemento unitario de la gramática.

Por supuesto, no se analiza lo mismo:

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

Entonces, por el bien de la legibilidad y el uso del lenguaje como fue pensado, el uso is not .

No usarlo no es sabio.


El código debe escribirse para que sea comprensible para el programador primero y luego para el compilador o intérprete. La construcción "no es" se asemeja más al inglés que "no es".


Es preferible utilizar el operador is not en lugar de negar el resultado por razones estilísticas. " if x is not None: " se lee igual que en inglés, pero " if not x is None: " requiere comprensión de la prioridad del operador y no se lee como inglés.

Si hay una diferencia de rendimiento en la que is not mi dinero, is not , pero es casi seguro que esta no es la motivación para la decisión de preferir esa técnica. Obviamente, sería dependiente de la implementación. Ya is no es anulable, debería ser fácil optimizar cualquier distinción de todos modos.


La respuesta es más simple de lo que la gente lo está haciendo.

No hay ninguna ventaja técnica de ninguna manera, y "x no es y" es lo que todos los demás usan , lo que lo convierte en el claro ganador. No importa que "se parezca más al inglés" o no; todo el mundo lo usa, lo que significa que todos los usuarios de Python, incluso los usuarios chinos, cuyo lenguaje no tiene nada que ver con Python, lo entenderán de un vistazo, donde la sintaxis un poco menos común tomará un par de ciclos adicionales para analizar.

No seas diferente solo por ser diferente, al menos en este campo.


No hay diferencia de rendimiento, ya que se compilan al mismo bytecode:

Python 2.6.2 (r262:71600, Apr 15 2009, 07:20:39) >>> import dis >>> def f(x): ... return x is not None ... >>> dis.dis(f) 2 0 LOAD_FAST 0 (x) 3 LOAD_CONST 0 (None) 6 COMPARE_OP 9 (is not) 9 RETURN_VALUE >>> def g(x): ... return not x is None ... >>> dis.dis(g) 2 0 LOAD_FAST 0 (x) 3 LOAD_CONST 0 (None) 6 COMPARE_OP 9 (is not) 9 RETURN_VALUE

Estilísticamente, trato de evitar que not x is y . Aunque el compilador siempre lo tratará como not (x is y) , un lector humano podría malinterpretar el constructo como (not x) is y . Si escribo x is not y entonces no hay ambigüedad.


Personalmente, yo uso

if not (x is None):

lo cual se entiende inmediatamente sin ambigüedad por parte de todos los programadores, incluso aquellos que no son expertos en la sintaxis de Python.


Preferiría que la forma más legible x is not y de lo que pensaría cómo escribir la prioridad de manejo de código de los operadores para producir un código mucho más legible.


Prueba esto:

if x != None: # do stuff with x


Tanto la guía de estilo de Google como la de Python son las mejores prácticas:

if x is not None: # Do something about x

Usar not x puede causar 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 te interese ver qué literales se evalúan como True o False en Python:

Editar para comentario a continuación:

Acabo de hacer algunas pruebas más. not x es ninguno no niega x primero y luego se compara con None . De hecho, parece que el operador tiene una 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 es solo, en mi opinión sincera, 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 demostrarlo de otra manera).

Esto significa que if x is not None tiene el resultado exacto como if not x is None . Me quedo corregido. Gracias bukzor.

Sin embargo, mi respuesta sigue en pie: use el convencional if x is not None . :]


if not x is None es más similar a otros lenguajes de programación, pero if x is not None definitivamente suena más claro (y es más correcto gramaticalmente en inglés) para mí.

Dicho esto, parece que es más una cuestión de preferencia para mí.