2010-07-25 24 views
8

Python dice que * y/tienen la misma precedencia.
Sé que las expresiones en python se evalúan de izquierda a derecha.Precedente del operador de Python

puedo confiar en que y asumir que j j/m es siempre igual a (j j)/m evitando los paréntesis?
Si este es el caso ¿puedo suponer que esto se aplica a los operadores con la misma precedencia en general?


PS: La pregunta, ya que está muy bien para mis propósitos, que llegué a ella, mientras que la lectura de número entero de sólo código (como el ejemplo anterior) sin paréntesis, que en el momento parecía mucho sospechoso para mí .

+7

"Explicit is better than implicit.", "Ante la ambigüedad, rechace la tentación de adivinar". - PEP 20 – msw

+0

british: Si estaba leyendo "code integer only", tiene un problema mucho mayor: ¿Qué versión de Python estaba destinada a ser utilizada para ejecutarla? ¿El código tiene 'desde __future__ división de importación' en el frente? ¿Debería leer '/' como y/o cambiarse a '//'? –

+0

@John Machin:/significa división entera en ese caso, es python 2.6 sin las cosas del futuro, noté que los códigos como j * j/m (j * j)/m eran iguales, pero temía la consistencia si este comportamiento. –

Respuesta

14

Sí: diferentes operadores con la misma precedencia son asociativos de la izquierda; es decir, se operarán los dos objetos más a la izquierda, luego el resultado y el 3er artículo, y así sucesivamente.

Una excepción es el operador **:

>>> 2 ** 2 ** 3 
256 

Además, los operadores de comparación (==, >, etcétera) no se comportan de una manera asociativa, pero en lugar de traducir x [cmp] y [cmp] z en (x [cmp] y) and (y [cmp] z).

+6

La asignación no es realmente una expresión en Python, y '=' no es un operador en el sentido normal; la precedencia del operador no se aplica. La asignación a objetivos múltiples se define explícitamente en la gramática para ser exactamente eso: asignar el mismo objeto a múltiples objetivos. –

+2

¡Error sobre la asignación, los pls cambian de ejemplo! El único operador en Python asociado de derecha a izquierda es '**', como en '2 ** 3 ** 4' –

+0

@Amber: (1) como @Nas Banov ha dicho,' ** 'es el ÚNICO El operador de Python que asocia a la derecha (2) que tiene una asociación correcta con él mismo es el resultado sin complicaciones de los hechos [1] (3) los operadores de comparación no son asociativos ... 'a

3

Respuesta corta: sí.

Los Python documentation says the following:

Los operadores en la misma caja tienen la misma prioridad. A menos que se proporcione explícitamente la sintaxis, los operadores son binarios. Operadores en el mismo grupo de cuadro de izquierda a derecha (excepto para las comparaciones, incluidas las pruebas, que tienen la misma precedencia y cadena de izquierda a derecha ... y la exponenciación, que se agrupa de derecha a izquierda).

Así, en otras palabras, la respuesta a su pregunta es sí, los operadores con la misma precedencia se grupo de izquierda a derecha, aparte de Comparisions which chain rather than group:

>>> x = 0 
>>> y = 0 
>>> x == y == True 
False 
>>> (x == y) == True 
True 
>>> x == (y == True) 
True 

y exponentation:

>>> 2 ** 2 ** 3 
256 
>>> (2 ** 2) ** 3 
64 
>>> 2 ** (2 ** 3) 
256 

también , en la asignación, el lado derecho se evalúa antes del lado izquierdo:

>>> x = 1 
>>> y = x = 2 
>>> y 
2 
+3

La asignación no es un operador (ver arriba), y los objetivos son de hecho * no * evaluados de derecha a izquierda.Se evalúa el rhs de la asignación, y luego los objetivos se evalúan * de izquierda a derecha * y asignados a. Puede ver la distinción cuando verifica el orden de las llamadas de función en, por ejemplo, 'a(). A, b(). B = c(). C': verá que se llama a' c() ', luego Se recupera el atributo 'c', luego se llama' a() 'y se asigna el atributo' a', y solo entonces el mismo para 'b()' –

+0

No quise dar a entender que la asignación era un operador, esto es por qué es el último He cambiado un poco la redacción sobre la asignación. –

+0

Su redacción todavía implica que el orden de evaluación de 'x' e' y' es importante para el resultado asignado a 'y'. No es asi. Los valores de 'x' y' y' nunca están involucrados en la asignación. 'y = x = 2' significa estrictamente" asignar '2' a' y' y a 'x'", no "asignar' 2' a 'x', luego el valor resultante de' x' a 'y'" (que, de nuevo, puede ver cuando involucra objetivos de asignación más complejos, como cuando se usan propiedades que se asignan a valores diferentes a los que les asigna. –

13

Pero, si es ambiguo para usted, el codificador, y debe ser porque tiene que preguntar, entonces espere que sea al menos tan ambiguo para el lector y desperdicie un par de octetos para mayor claridad.

Confiar en las reglas de prioridad es genial si usted es un compilador.

añaden las respuestas a los comentarios:

Para la persona de código que se encuentra con una ambigüedad que requiere la consulta fuera para el aseguramiento de la lectura, se debe asumir que el lector siguiente será menos inteligente que tú y los guarda el esfuerzo y error humano evitable de analizar el mismo constructo y agregar el paréntesis para ellos.

Ocurre que incluso la respuesta aceptada era incorrecta (por razones, no tiene efecto, mira su primer comentario) de la que no tenía conocimiento y tampoco una fracción de los que la votaron por encima.

En cuanto a la afirmación sobre el álgebra básica, el ejemplo particular utilizado en el OP es instructivo. Independientemente de la precedencia del operador, la expresión j * (j/m) es algebraicamente idéntica a (j * j)/m. Desafortunadamente, el álgebra de Python es solo una aproximación del álgebra "ideal platónico" que podría arrojar respuestas incorrectas para cualquiera de las formas dependiendo de las magnitudes de j y m. Por ejemplo:

>>> m = 1e306 
>>> m 
1e+306 
>>> j = 1e307 
>>> j 
9.9999999999999999e+306 
>>> j/m 
10.0 
>>> j*j 
inf 
>>> j * (j/m) 
1e+308 
>>> (j * j)/m 
inf 
>>> ((j * j)/m) == (j * (j/m)) 
False 

Así que de hecho la propiedad de identidad de Python (y mi FPU) cuasi-álgebra no se sostiene. Y esto puede ser diferente en su máquina para que los documentation notes: números de punto

flotantes se implementan utilizando doble en C. Todas las apuestas en su precisión están apagados a menos que suceda a conocer la máquina que está trabajando .

Podría decirse que uno no tiene negocios que trabajan en el borde peluda de desbordamiento, y eso es cierto hasta cierto punto, pero retirado del contexto, la expresión es indeterminada dado una orden de operaciones y "correcta" en virtud de otro.

+0

Daría +10 a esta respuesta si pudiera. :) Este es un punto muy importante. – EOL

+0

Para obtener un ápice filosófico, la respuesta aceptada es, de hecho, la respuesta correcta a la pregunta que se hizo. Lo cual debe significar que la pregunta es incorrecta, y es en el punto donde se pregunta sobre "evitar los paréntesis". Habiendo tenido que atravesar recientemente una biblioteca que funciona pero tortuosamente ilegible, me he vuelto extremadamente sensible a la diferencia en los estándares expresos de Python y su uso en la práctica común. – msw

+2

¿por qué asumes que estoy tratando de escribir un código? ¿Qué pasa si ... estoy tratando de leer? –

Cuestiones relacionadas