python python-2.7 python-3.x

python - ¿Por qué "no(verdadero) en[falso, verdadero]" devuelve falso?



python-2.7 python-3.x (9)

Si hago esto:

>>> False in [False, True] True

Eso devuelve True . Simplemente porque False está en la lista.

Pero si lo hago:

>>> not(True) in [False, True] False

Eso devuelve False . Mientras que not(True) es igual a False :

>>> not(True) False

¿Por qué?


Está evaluando como not True in [False, True] , que devuelve False porque True está en [False, True]

Si intentas

>>>(not(True)) in [False, True] True

Obtienes el resultado esperado.


Junto con las otras respuestas que mencionaron que la precedencia de not es menor que in , in realidad su declaración es equivalente a:

not (True in [False, True])

Pero tenga en cuenta que si no separa su condición de las otras, python usará 2 roles ( precedence o chaining ) para separar eso, y en este caso python usó precedencia. Además, tenga en cuenta que si desea separar una condición, debe poner todas las condiciones entre paréntesis, no solo el objeto o el valor:

(not True) in [False, True]

Pero como se mencionó, hay otra modificación por python en los operadores que está encadenando :

Basado en la 3.x Python:

Tenga en cuenta que las comparaciones, las pruebas de membresía y las pruebas de identidad tienen la misma prioridad y tienen una función de encadenamiento de izquierda a derecha como se describe en la sección Comparaciones.

Por ejemplo, el resultado de la siguiente declaración es False :

>>> True == False in [False, True] False

Porque python encadenará las declaraciones de la siguiente manera:

(True == False) and (False in [False, True])

Que es exactamente False and True que es False .

Puede suponer que el objeto central se compartirá entre 2 operaciones y otros objetos (falso en este caso).

Y tenga en cuenta que también es cierto para todas las comparaciones, incluidas las pruebas de membresía y las operaciones de pruebas de identidad que son los siguientes operandos:

in, not in, is, is not, <, <=, >, >=, !=, ==

Ejemplo:

>>> 1 in [1,2] == True False

Otro ejemplo famoso es el rango de números:

7<x<20

que es igual a:

7<x and x<20


Para aclarar algunas de las otras respuestas, agregar paréntesis después de un operador unario no cambia su precedencia. not(True) no hace que not una más estrechamente a True . Es solo un conjunto redundante de paréntesis alrededor de True . Es muy parecido a (True) in [True, False] . Los paréntesis no hacen nada. Si desea que el enlace sea más ajustado, debe poner los paréntesis alrededor de toda la expresión, es decir, tanto el operador como el operando, es decir, (not True) in [True, False] .

Para ver esto de otra manera, considere

>>> -2**2 -4

** une más fuertemente que - , por lo que obtienes el negativo de dos al cuadrado, no el cuadrado de dos negativos (que sería positivo cuatro).

¿Qué pasaría si quisieras el cuadrado de dos negativos? Obviamente, agregarías paréntesis:

>>> (-2)**2 4

Sin embargo, no es razonable esperar que lo siguiente dé 4

>>> -(2)**2 -4

porque -(2) es lo mismo que -2 . Los paréntesis no hacen absolutamente nada. not(True) es exactamente lo mismo.


Precedencia del operador. in une más fuertemente que not , por lo que su expresión es equivalente a not((True) in [False, True]) .


Se trata de la precedencia del operador ( in es más fuerte que not ). Pero se puede corregir fácilmente agregando paréntesis en el lugar correcto:

(not(True)) in [False, True] # prints true

escritura:

not(True) in [False, True]

es lo mismo que:

not((True) in [False, True])

que se ve si True está en la lista y devuelve el "no" del resultado.


Veámoslo como una operación de comprobación de la contención de la colección: [False, True] es una lista que contiene algunos elementos.

La expresión True in [False, True] devuelve True , ya que True es un elemento contenido en la lista.

Por lo tanto, not True in [False, True] da el "opuesto booleano", not resultado de la expresión anterior (sin paréntesis para preservar la precedencia, ya que tiene mayor precedencia que el operador). Por lo tanto, not True resultará False .

Por otro lado, (not True) in [False, True] , es igual a False in [False, True] , que es True ( False está contenido en la lista).


3.x está la documentación sobre la precedencia del operador

in binds tighter than not

Hacerlo servirá así

>>> (not True) in [False, True] True


Precedencia del operador 2.x , 3.x La precedencia de not es menor que la de in . Entonces es equivalente a:

>>> not ((True) in [False, True]) False

Esto es lo que quieres:

>>> (not True) in [False, True] True

Como señala @Ben: se recomienda no escribir nunca not(True) , preferir not True . El primero hace que parezca una llamada de función, mientras que not es un operador, no una función.


not x in y se evalúa como x not in y

Puede ver exactamente lo que está sucediendo desmontando el código. El primer caso funciona como espera:

>>> x = lambda: False in [False, True] >>> dis.dis(x) 1 0 LOAD_GLOBAL 0 (False) 3 LOAD_GLOBAL 0 (False) 6 LOAD_GLOBAL 1 (True) 9 BUILD_LIST 2 12 COMPARE_OP 6 (in) 15 RETURN_VALUE

El segundo caso, se evalúa como True not in [False, True] , que es False claramente:

>>> x = lambda: not(True) in [False, True] >>> dis.dis(x) 1 0 LOAD_GLOBAL 0 (True) 3 LOAD_GLOBAL 1 (False) 6 LOAD_GLOBAL 0 (True) 9 BUILD_LIST 2 12 COMPARE_OP 7 (not in) 15 RETURN_VALUE >>>

Lo que quería expresar en su lugar era (not(True)) in [False, True] , que como se esperaba es True , y puede ver por qué:

>>> x = lambda: (not(True)) in [False, True] >>> dis.dis(x) 1 0 LOAD_GLOBAL 0 (True) 3 UNARY_NOT 4 LOAD_GLOBAL 1 (False) 7 LOAD_GLOBAL 0 (True) 10 BUILD_LIST 2 13 COMPARE_OP 6 (in) 16 RETURN_VALUE