logical - Python Y operador en dos listas booleanas-¿cómo?
python logical operators example (7)
Tengo dos listas booleanas, por ejemplo,
x=[True,True,False,False]
y=[True,False,True,False]
Quiero Y estas listas juntas, con el resultado esperado:
xy=[True,False,False,False]
Pensé que la expresión x and y
funcionaría, pero llegué a descubrir que no es así: de hecho, (x and y) != (y and x)
Salida de x and y
: [True,False,True,False]
Salida de y and x
: [True,True,False,False]
El uso de la lista de comprensión tiene salida correcta. ¡Uf!
xy = [x[i] and y[i] for i in range(len(x)]
Tenga en cuenta que no pude encontrar ninguna referencia que me dijera que el operador AND funcionaría como lo intenté con x e y. Pero es fácil probar cosas en Python. ¿Puede alguien explicarme lo que está pasando con x and y
?
Y aquí hay un programa de prueba simple:
import random
random.seed()
n = 10
x = [random.random() > 0.5 for i in range(n)]
y = [random.random() > 0.5 for i in range(n)]
# Next two methods look sensible, but do not work
a = x and y
z = y and x
# Next: apparently only the list comprehension method is correct
xy = [x[i] and y[i] for i in range(n)]
print ''x : %s''%str(x)
print ''y : %s''%str(y)
print ''x and y : %s''%str(a)
print ''y and x : %s''%str(z)
print ''[x and y]: %s''%str(xy)
Además de lo que @Martijn Pieters ha respondido, solo agregaría el siguiente código para explicar and
/ or
operaciones en acción.
and
devuelve el primer valor falso encontrado en el último argumento evaluado.
De forma similar or
devuelve el primer valor de verdad encontrado en el último argumento evaluado.
nl1 = [3,3,3,3,0,0,0,0]
nl2 = [2,2,0,0,2,2,0,0]
nl3 = [1,0,1,0,1,0,1,0]
and_list = [a and b and c for a,b,c in zip(nl1,nl2,nl3)]
or_list = [a or b or c for a,b,c in zip(nl1,nl2,nl3)]
Los valores son
and_list = [1, 0, 0, 0, 0, 0, 0, 0]
or_list = [3, 3, 3, 3, 2, 2, 1, 0]
En lugar de usar
[a and b for a, b in zip(x, y)]
uno podría usar la posibilidad de numpy para multiplicar valores bool:
(np.array(x)*np.array(y))
>> array([ True, False, False, False], dtype=bool)
¿O me olvido de un caso especial?
Esto debería hacer lo que quieras:
xy = [a and b for a, b in zip(x, y)]
La razón por la que x and y
devuelve y
e y and x
devuelve x
es porque los operadores booleanos en python devuelven el último valor verificado que determina la veracidad de la expresión. Las list
no están vacías se evalúan como True
, y dado que ambos operandos requieren la True
, el último es el segundo. Contraste con x or y
, que devolvería x
porque no es necesario verificar y
para determinar la veracidad de la expresión.
Podrías usar numpy:
>>> import numpy as np
>>> x=np.array([True,True,False,False])
>>> y=np.array([True,False,True,False])
>>> x & y
array([ True, False, False, False], dtype=bool)
Numpy permite operaciones numéricas y lógicas en arreglos tales como:
>>> z=np.array([1,2,3,4])
>>> z+1
array([2, 3, 4, 5])
Puede realizar bitwise y con el operador &
.
En lugar de una lista de comprensión, puede usar numpy para generar la matriz booleana directamente de esta manera:
>>> np.random.random(10)>.5
array([ True, True, True, False, False, True, True, False, False, False], dtype=bool)
Puedes usar la función zip
x=[True,True,False,False]
y=[True,False,True,False]
z=[a and b for a,b in zip(x,y)]
and
no es necesariamente un operador booleano; devuelve uno de sus dos argumentos, independientemente de su tipo. Si el primer argumento es false-ish ( False
, cero numérico o una cadena / contenedor vacío), devuelve ese argumento. De lo contrario, devuelve el segundo argumento.
En su caso, tanto x
como y
son listas no vacías, por lo que el primer argumento es siempre verdadero, lo que significa que x and y
devuelve y
e y and x
devuelve x
.
and
simplemente devuelve el primer o el segundo operando, según su valor de verdad. Si el primer operando se considera falso, se devuelve, de lo contrario se devuelve el otro operando.
Las listas se consideran verdaderas cuando no están vacías , por lo que ambas listas se consideran verdaderas. Sus contenidos no juegan un papel aquí .
Debido a que ambas listas no están vacías, x and y
simplemente devuelven el segundo objeto de lista; solo si x
estaba vacío sería devuelto en su lugar:
>>> [True, False] and [''foo'', ''bar'']
[''foo'', ''bar'']
>>> [] and [''foo'', ''bar'']
[]
Vea la sección de prueba de valor de verdad en la documentación de Python:
Cualquier objeto puede ser probado para valor de verdad, para uso en una condición
if
owhile
o como operando de las operaciones booleanas a continuación. Los siguientes valores se consideran falsos:[...]
- cualquier secuencia vacía, por ejemplo,
''''
,()
,[]
.[...]
Todos los demás valores se consideran verdaderos , por lo que los objetos de muchos tipos siempre son verdaderos.
(énfasis mío), y la sección de operaciones booleanas justo debajo de eso:
x and y
si x es falso, entonces x , si no yEste es un operador de cortocircuito, por lo que solo evalúa el segundo argumento si el primero es
True
.
De hecho, necesita probar los valores contenidos en las listas explícitamente. Puede hacerlo con una lista de comprensión, como descubrió. Puede reescribirlo con la función zip()
para emparejar los valores:
[a and b for a, b in zip(x, y)]