¿Por qué (1 en [1,0] == Verdadero) se evalúa como Falso?

153

Cuando estaba buscando respuestas a esta pregunta , descubrí que no entendía mi propia respuesta.

Realmente no entiendo cómo se analiza esto. ¿Por qué el segundo ejemplo devuelve False?

>>> 1 in [1,0]             # This is expected
True
>>> 1 in [1,0] == True     # This is strange
False
>>> (1 in [1,0]) == True   # This is what I wanted it to be
True
>>> 1 in ([1,0] == True)   # But it's not just a precedence issue!
                           # It did not raise an exception on the second example.

Traceback (most recent call last):
  File "<pyshell#4>", line 1, in <module>
    1 in ([1,0] == True)
TypeError: argument of type 'bool' is not iterable

Gracias por cualquier ayuda. Creo que me estoy perdiendo algo realmente obvio.


Creo que esto es sutilmente diferente al duplicado vinculado:

¿Por qué la expresión 0 <0 == 0 devuelve False en Python? .

Ambas preguntas tienen que ver con la comprensión humana de la expresión. Parecía haber dos formas (en mi opinión) de evaluar la expresión. Por supuesto, ninguno era correcto, pero en mi ejemplo, la última interpretación es imposible.

Mirándote 0 < 0 == 0podrías imaginar que cada mitad es evaluada y tiene sentido como una expresión

>>> (0 < 0) == 0
True
>>> 0 < (0 == 0)
True

Entonces el enlace responde por qué esto evalúa False:

>>> 0 < 0 == 0
False

Pero con mi ejemplo 1 in ([1,0] == True)no tiene sentido como una expresión, por lo que en lugar de haber dos interpretaciones posibles (ciertamente erróneas), solo una parece posible:

>>> (1 in [1,0]) == True
Peter Wood
fuente
1
Precedencia del operador ... la ==unión es más fuerte que in, por lo que [1,0] == Trueprimero se evalúa, luego el resultado de eso se alimenta a1 in other_result .
Marc B
He eliminado la etiqueta Python-2.7, ya que Python 3.2 se comporta de la misma manera.
lvc
1
@Marc B: no explica la segunda expresión
Scott Hunter
32
@MarcB, la pregunta incluyó una prueba usando paréntesis para refutar esa interpretación.
Mark Ransom

Respuestas:

194

Python realmente aplica el operador de comparación encadenado aquí. La expresión se traduce a

(1 in [1, 0]) and ([1, 0] == True)

que es obviamente False.

Esto también sucede para expresiones como

a < b < c

que se traducen en

(a < b) and (b < c)

(sin evaluar bdos veces).

Consulte la documentación del lenguaje Python para más detalles.

Sven Marnach
fuente
40
Prueba adicional de esto, 1 in [1, 0] == [1, 0]evalúa a True.
Andrew Clark
9
Durante mucho tiempo pensé en esto como una verruga del lenguaje. Hubiera preferido que el inoperador tenga una mayor prioridad que otros operadores de comparación y que no se encadene. Pero tal vez me falta un caso de uso.
Steven Rumbalski
3
buena captura, ni siquiera pensé en eso. No tiene mucho sentido permitir el encadenamiento in- después de todo x < y < ztiene sentido, pero no tanto conx in y in z
BlueRaja - Danny Pflughoeft
77
@Sven Útil: quizás. Legible: definitivamente no. Python pretende emular la tipografía matemática común con esta convención, pero cuando se usa con inesto simplemente ya no es el caso y lo hace bastante contra-intuitivo.
Konrad Rudolph
66
@KonradRudolph: He visto pensar como "1 ≤ x ∈ ℝ" en textos matemáticos más de una vez, pero básicamente estoy de acuerdo con usted.
Sven Marnach