Je suis confus quant au moment d'utiliser un opérateur booléen ou binaire
and vs &, or vs |
Est-ce que quelqu'un pourrait m'éclairer sur le moment où je les utiliserais et quand utiliser l'un sur l'autre affectera mes résultats?
Voici quelques lignes directrices:
Le comportement de court-circuitage est utile dans des expressions comme celle-ci:
if x is not None and x.foo == 42:
# ...
Cela ne fonctionnerait pas correctement avec l'opérateur binaire &
car les deux côtés seraient toujours évalués, donnant AttributeError: 'NoneType' object has no attribute 'foo'
. Lorsque vous utilisez l'opérateur booléen and
, la deuxième expression n'est pas évaluée lorsque la première est fausse. De même, or
n'évalue pas le deuxième argument si le premier est True.
En théorie, and
et or
proviennent directement de la logique booléenne (et fonctionnent donc sur deux booléens pour produire un booléen), tandis que &
et |
appliquent les booléens et/ou les bits individuels d'entiers. Il y a beaucoup de questions ici sur la façon dont ce dernier fonctionne exactement.
Voici des différences pratiques qui peuvent affecter vos résultats:
and
et or
court-circuiter, c'est-à-dire que True or sys.exit(1)
ne se ferme pas, car pour une certaine valeur (True or ...
, False and ...
) du premier opérande, le second ne changerait pas le résultat = n'a pas besoin d'être évalué. Mais |
et &
ne court-circuite pas - True | sys.exit(1)
vous jette hors du REPL.&
et |
sont des opérateurs normaux et peuvent être surchargés - and
et or
sont forgés dans le langage (bien qu'au moins en Python, la méthode spéciale de coercition sur boolean peut avoir Effets secondaires).and
et or
retournent (toujours? jamais vraiment comprendre cela, je n'en avais pas besoin) la valeur d'un opérande au lieu de True
ou False
. Cela ne change pas la signification des expressions booléennes dans les conditions - 1 or True
est 1
, mais 1
est également vrai. Mais il était autrefois utilisé pour émuler un opérateur conditionnel (cond ? true_val : false_val
en syntaxe C, true_val if cond else false_val
en Python depuis quelques années). Pour &
et |
, le type de résultat dépend de la manière dont les opérandes surchargent les méthodes spéciales respectives (True & False
est False
, 99 & 7
est 3
, pour les ensembles c'est son union/intersection ...).Mais même quand, par exemple a_boolean & another_boolean
fonctionnerait de manière identique, la bonne solution utilisant and
- tout simplement parce que and
et or
sont associés à une expression booléenne et à une condition, alors que &
et |
correspondent à des virages.
Voici une autre différence, qui me laissait perplexe depuis quelque temps: parce que &
(et d'autres opérateurs au niveau des bits) ont une priorité plus élevée que and
(et d'autres opérateurs booléens), les expressions suivantes ont une valeur différente:
0 < 1 & 0 < 2
versus
0 < 1 and 0 < 2
À savoir, le premier produit False
car il est équivalent à 0 < (1 & 0) < 2
, d'où 0 < 0 < 2
, d'où 0 < 0 and 0 < 2
.
Si vous essayez d'effectuer des opérations booléennes par élément dans numpy
, la réponse est quelque peu différente. Vous pouvez utiliser &
et |
pour les opérations booléennes par élément, mais and
et or
renverront une erreur de valeur.
Pour être sûr, vous pouvez utiliser les fonctions logiques numpy .
np.array([True, False, True]) | np.array([True, False, False])
# array([ True, False, True], dtype=bool)
np.array([True, False, True]) or np.array([True, False, False])
# ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
np.logical_or(np.array([True, False, True]), np.array([True, False, False]))
# array([ True, False, True], dtype=bool)
Les opérations booléennes sont des opérations logiques.
Les opérations au niveau du bit sont des opérations sur des bits binaires.
Opérations binaires:
>>> k = 1
>>> z = 3
>>> k & z
1
>>> k | z
3
Les opérations:
And & 1 if both bits are 1, 0 otherwise
Or | 1 if either bit is 1
Xor ^ 1 if the bits are different, 0 if they're the same
Not ~ Flip each bit
Quelques-unes des utilisations des opérations au niveau des bits:
1) Définition et effacement des bits
Opérations booléennes:
>>> k = True
>>> z = False
>>> k & z # and
False
>>> k | z # or
True
>>>
L'indice est dans le nom:
Bien qu'il soit possible et même parfois souhaitable (généralement pour des raisons d'efficacité) d'effectuer des opérations logiques avec des opérateurs au niveau du bit, vous devez généralement les éviter à cette fin pour éviter des bogues subtils et des effets secondaires indésirables.
Si vous devez manipuler des bits, les opérateurs au niveau du bit sont construits à cet effet. Le livre amusant: Hackers Delight contient quelques exemples intéressants et véritablement utiles de ce que l’on peut réaliser avec le bricolage.
La règle générale consiste à utiliser l'opérateur approprié pour les opérandes existants. Utilisez des opérateurs booléens (logiques) avec des opérandes booléens et des opérateurs au niveau des bits avec des opérandes intégraux (plus larges) (remarque: False est équivalent à 0 et True à 1). Le seul scénario "délicat" consiste à appliquer des opérateurs booléens à des opérandes non booléens.
Prenons un exemple simple, comme décrit dans [SO]: Python - Différences entre 'et' et '&' [duplicate] : 5 & 7
vs.5 and 7
.
Pour le bitwise and (&), les choses sont assez simples:
5 = 0b101 7 = 0b111 ----------------- 5 & 7 = 0b101 = 5
Pour le logique et, voici ce que [Python 3]: Opérations booléennes États (emphasis est le mien):
(Notez que ni et ni ni ne restreint la valeur et le type renvoyés à False et True, mais plutôt renvoie le dernier argument évalué .
Exemple:
>>> 5 and 7 7 >>> 7 and 5 5
Bien entendu, il en va de même pour | _ vs.ou.
Booléen 'et' vs bitwise '&':
Pseudo-code/Python m'a aidé à comprendre la différence entre ceux-ci:
def boolAnd(A, B):
# boolean 'and' returns either A or B
if A == False:
return A
else:
return B
def bitwiseAnd(A , B):
# binary representation (e.g. 9 is '1001', 1 is '0001', etc.)
binA = binary(A)
binB = binary(B)
# perform boolean 'and' on each pair of binaries in (A, B)
# then return the result:
# equivalent to: return ''.join([x*y for (x,y) in Zip(binA, binB)])
# assuming binA and binB are the same length
result = []
for i in range(len(binA)):
compar = boolAnd(binA[i], binB[i])
result.append(compar)
# we want to return a string of 1s and 0s, not a list
return ''.join(result)
Opérations logiques
sont généralement utilisés pour les instructions conditionnelles. Par exemple:
if a==2 and b >10 then /*Do something...*/ endif
Cela signifie que si les deux conditions ((a = 2) (b> 10)) sont vraies en même temps, le corps de l'instruction conditionnelle peut être exécuté.
Opérations sur les bits
Les opérations sur les bits peuvent être utilisées pour la manipulation et l'extraction de données. Par exemple, si vous souhaitez extraire quatre bits de poids le moins significatif (LSB) d'un entier, procédez comme suit:
Extraction:
poo & 0x000F
Masquage:
poo | 0xFFF0