J'obtiens un résultat bizarre et j'essaie d'appliquer l'opérateur and
ou or
à 2 listes booléennes en python. J'obtiens en fait exactement le contraire de ce que j'attendais.
[True, False, False] and [True, True, False]
> [True, True, False]
[True, False, False] or [True, True, False]
> [True, False, False]
Est-ce normal, et si oui, pourquoi?
Vos listes ne comparent pas chaque valeur individuelle, elles comparent l'existence de valeurs dans la liste.
Pour toutes les variables véridiques a
et b
:
a and b
> b #The program evaluates a, a is truthy, it evaluates b, b is truthy, so it returns the last evaluated value, b.
a or b
> a #The program evaluates a, a is truthy, so the or statement is true, so it returns the last evaluated value, a.
Maintenant, la vérité dépend du type. Par exemple, les entiers sont vrais pour my_int != 0
, et sont fausses pour my_int == 0
. Donc si vous avez:
a = 0
b = 1
a or b
> b #The program evaluates a, a is falsy, so the or statement goes on to evaluate b, b is truthy, so the or statement is true and it returns the last evaluated value b.
Si vous vouliez réellement des opérations booléennes par élément entre vos deux listes, envisagez d'utiliser le module numpy
:
>>> import numpy as np
>>> a = np.array([True, False, False])
>>> b = np.array([True, True, False])
>>> a & b
array([ True, False, False], dtype=bool)
>>> a | b
array([ True, True, False], dtype=bool)
C'est normal, car and
et or
évaluent en fait l'un de leurs opérandes. x and y
est comme
def and(x, y):
if x:
return y
return x
tandis que x or y
est comme
def or(x, y):
if x:
return x
return y
Étant donné que vos deux listes contiennent des valeurs, elles sont toutes les deux "truey" donc and
évalue le deuxième opérande et or
évalue le premier.
Je pense que vous avez besoin de quelque chose comme ça:
[x and y for x, y in Zip([True, False, False], [True, True, False])]
Les deux listes sont véridiques car elles ne sont pas vides.
and
et or
renvoient l'opérande qui a décidé de la valeur de l'opération.
Si le côté gauche de and
est véridique, il doit évaluer le côté droit, car il pourrait être faux, ce qui rendrait toute l'opération fausse (false and
tout est faux). Par conséquent, il renvoie le côté droit.
Si le côté gauche de or
est véridique, il n'a pas besoin d'évaluer le côté droit, car il sait déjà que l'expression est vraie (true or
tout est vrai). Il renvoie donc le côté gauche.
Si vous souhaitez effectuer des comparaisons par paire des éléments de la liste, utilisez une compréhension de la liste, par exemple:
[x or y for (x, y) in Zip(a, b)] # a and b are your lists
Manière très pratique:
>>> import numpy as np
>>> np.logical_and([True, False, False], [True, True, False])
array([ True, False, False], dtype=bool)
>>> np.logical_or([True, False, False], [True, True, False])
array([ True, True, False], dtype=bool)
Plus fonctionnel:
from operator import or_, and_
from itertools import starmap
a = [True, False, False]
b = [True, True, False]
starmap(or_, Zip(a,b)) # [True, True, False]
starmap(and_, Zip(a,b)) # [True, False, False]