Pregunta El operador de Python en (__contains__) devuelve un bool cuyo valor no es True ni False


Como se esperaba, 1 no está contenido por la tupla vacía

>>> 1 in ()
False

pero el False el valor devuelto no es igual a False

>>> 1 in () == False
False

Mirándolo de otra manera, el in el operador devuelve un bool que no es ni True ni False:

>>> type(1 in ())
<type 'bool'>
>>> 1 in () == True, 1 in () == False
(False, False)

Sin embargo, el comportamiento normal se reanuda si la expresión original está entre paréntesis

>>> (1 in ()) == False
True

o su valor se almacena en una variable

>>> value = 1 in ()
>>> value == False
True

Este comportamiento se observa tanto en Python 2 como en Python 3.

¿Puedes explicar lo que está pasando?


32
2017-11-03 09:38


origen


Respuestas:


Te estás enfrentando al encadenamiento de operadores de comparación; 1 in () == False hace no media (1 in ()) == False.

Por el contrario, las comparaciones están encadenadas y la expresión realmente significa:

(1 in ()) and (() == False)

Porque (1 in ()) ya es falso, la segunda mitad de la expresión encadenada se ignora por completo (desde False and something_else devoluciones False cualquiera que sea el valor de something_else sería).

Ver el documentación de expresiones de comparaciones:

Las comparaciones se pueden encadenar arbitrariamente, por ejemplo, x < y <= z es equivalente a x < y and y <= z, excepto eso y se evalúa solo una vez (pero en ambos casos) z no se evalúa en absoluto cuando x < y se encuentra que es falso).

Para el registro, <, >, ==, >=, <=, !=, is, is not, in y not in son todos los operadores de comparación (como lo es el obsoleto <>)

En general, no compare contra booleanos; simplemente prueba la expresión en sí misma. Si tu tener para probar contra un literal booleano, al menos use paréntesis y is operador, True y False son singletons, al igual que None:

>>> (1 in ()) is False
True

Esto se vuelve aún más confuso cuando los enteros están involucrados. El Python bool tipo es una subclase de int1. Como tal, False == 0 es cierto, como es True == 1. Por lo tanto, puede concebir operaciones encadenadas que casi parecen cuerdas:

3 > 1 == True

es cierto porque 3 > 1 y 1 == True son ambos verdaderos Pero la expresión:

3 > 2 == True

es falso, porque 2 == True Es falso.

1  bool es una subclase de int por razones históricas; Python no siempre tiene una bool Escriba y sobrecargue números enteros con un significado booleano como C lo hace. Fabricación bool una subclase mantuvo funcionando el código anterior.


45
2017-11-03 09:41