XOR signifie “ou exclusif”. L’idée est simple : le résultat est vrai quand les deux valeurs sont différentes, et faux quand elles sont identiques.
En Python, l’opérateur XOR s’écrit ^. Sur des entiers, il compare les bits un par un. Sur des booléens, il permet de vérifier qu’une seule des deux conditions est vraie.
print(5 ^ 3) # 6
print(True ^ False) # True
print(True ^ True) # False
Le piège classique est de croire que ^ sert à calculer une puissance. En Python, la puissance s’écrit avec **, pas avec ^.
print(2 ** 3) # 8
print(2 ^ 3) # 1
Cette différence explique beaucoup de résultats “bizarres” chez les débutants.
La réponse courte
Pour faire un XOR en Python, utilisez l’opérateur ^.
a = 5 # 0101 en binaire
b = 3 # 0011 en binaire
resultat = a ^ b
print(resultat) # 6
print(f"{resultat:04b}") # 0110
Le XOR compare chaque bit :
0101
0011
----
0110
Un bit vaut 1 dans le résultat seulement si les deux bits comparés sont différents.
La table de vérité du XOR
La table de vérité du XOR tient en quatre cas :
| A | B | A XOR B |
|---|---|---|
False |
False |
False |
False |
True |
True |
True |
False |
True |
True |
True |
False |
Autrement dit : XOR répond à la question “exactement une des deux conditions est-elle vraie ?”.
En Python :
def xor_logique(a, b):
return a != b
print(xor_logique(False, False)) # False
print(xor_logique(False, True)) # True
print(xor_logique(True, False)) # True
print(xor_logique(True, True)) # False
Pour des booléens, a != b est souvent plus lisible que a ^ b, car il exprime directement l’idée de différence.
utilisateur_connecte = True
mode_invite = False
acces_possible = utilisateur_connecte != mode_invite
print(acces_possible) # True
Comment Python calcule un XOR bit par bit
Sur des entiers, Python applique XOR à l’écriture binaire des nombres. Prenons 5 ^ 3.
a = 5
b = 3
print(f"{a:04b}") # 0101
print(f"{b:04b}") # 0011
print(f"{a ^ b:04b}") # 0110
Lecture bit par bit :
Bit de a |
Bit de b |
Résultat |
|---|---|---|
| 0 | 0 | 0 |
| 1 | 0 | 1 |
| 0 | 1 | 1 |
| 1 | 1 | 0 |
Le résultat binaire 0110 vaut 6 en décimal.
Vous pouvez afficher les étapes dans une fonction :
def afficher_xor(a, b, largeur=8):
resultat = a ^ b
print(f"a = {a:>{largeur}d} {a:0{largeur}b}")
print(f"b = {b:>{largeur}d} {b:0{largeur}b}")
print(f"a ^ b = {resultat:>{largeur}d} {resultat:0{largeur}b}")
return resultat
afficher_xor(5, 3, largeur=4)
Résultat :
a = 5 0101
b = 3 0011
a ^ b = 6 0110
Cette visualisation est très utile pour comprendre les masques binaires.
XOR, OR et AND : ne pas confondre
Les trois opérateurs bitwise les plus fréquents sont &, | et ^.
| Opérateur | Nom | Idée simple |
|---|---|---|
& |
AND bitwise | garde 1 si les deux bits valent 1 |
| |
OR bitwise | garde 1 si au moins un bit vaut 1 |
^ |
XOR bitwise | garde 1 si les deux bits sont différents |
Exemple :
a = 0b1100
b = 0b1010
print(f"{a & b:04b}") # 1000
print(f"{a | b:04b}") # 1110
print(f"{a ^ b:04b}") # 0110
Le XOR n’est pas un simple “ou”. Avec OR, deux valeurs vraies donnent vrai. Avec XOR, deux valeurs vraies donnent faux.
print(True or True) # True
print(True ^ True) # False
C’est précisément ce qui rend XOR utile : il détecte une différence.
Utiliser XOR avec des booléens
Python accepte ^ entre deux booléens :
print(False ^ False) # False
print(False ^ True) # True
print(True ^ False) # True
print(True ^ True) # False
Mais dans du code applicatif, préférez souvent :
condition_a != condition_b
Exemple :
mot_de_passe_fourni = True
connexion_oauth = False
if mot_de_passe_fourni != connexion_oauth:
print("Une seule méthode de connexion est utilisée.")
else:
print("Configuration ambiguë.")
Cette forme est plus claire pour un lecteur qui ne pense pas immédiatement aux opérations bitwise.
Résoudre une équation XOR simple
XOR possède trois propriétés très pratiques :
x ^ x = 0
x ^ 0 = x
x ^ y = y ^ x
Ces propriétés permettent de retrouver une valeur inconnue.
Si :
a ^ b = c
alors :
a = c ^ b
b = c ^ a
Exemple en Python :
a = 42
b = 15
c = a ^ b
retrouve_a = c ^ b
retrouve_b = c ^ a
print(c) # 37
print(retrouve_a) # 42
print(retrouve_b) # 15
Pourquoi cela fonctionne ?
c ^ b = (a ^ b) ^ b
= a ^ (b ^ b)
= a ^ 0
= a
Cette logique revient souvent dans les exercices d’algorithmique.
Trouver l’élément unique dans une liste
Un exemple classique : dans une liste, tous les nombres apparaissent deux fois sauf un. XOR permet de retrouver ce nombre en une seule passe.
from functools import reduce
from operator import xor
valeurs = [9, 12, 9, 4, 12]
unique = reduce(xor, valeurs)
print(unique) # 4
Explication : chaque paire s’annule.
9 ^ 9 = 0
12 ^ 12 = 0
0 ^ 0 ^ 4 = 4
Version sans reduce, plus lisible pour débuter :
valeurs = [9, 12, 9, 4, 12]
resultat = 0
for valeur in valeurs:
resultat ^= valeur
print(resultat) # 4
Ce code est en O(n) en temps et en O(1) en mémoire. Il est donc très efficace pour ce cas précis.
Attention : cette méthode suppose que tous les autres nombres apparaissent exactement deux fois. Si les doublons ne respectent pas cette règle, le résultat ne correspond plus à “l’élément unique”.
Basculer un bit avec XOR
XOR est très pratique pour inverser certains bits. Si un bit est à 0, XOR avec 1 le met à 1. S’il est à 1, XOR avec 1 le remet à 0.
valeur = 0b1010
masque = 0b0010
resultat = valeur ^ masque
print(f"{valeur:04b}") # 1010
print(f"{masque:04b}") # 0010
print(f"{resultat:04b}") # 1000
Le deuxième bit en partant de la droite a été inversé.
Pour basculer plusieurs bits, mettez plusieurs 1 dans le masque :
valeur = 0b1010
masque = 0b0101
print(f"{valeur ^ masque:04b}") # 1111
Ce type de manipulation apparaît dans les flags binaires, les protocoles, certaines optimisations, les formats de fichiers ou les exercices de bas niveau.
XOR avec des ensembles Python
L’opérateur ^ ne sert pas seulement aux entiers. Python l’utilise aussi pour la différence symétrique entre ensembles.
a = {"python", "numpy", "pandas"}
b = {"python", "django", "pandas"}
print(a ^ b)
Résultat possible :
{'numpy', 'django'}
Ici, a ^ b garde les éléments présents dans un seul des deux ensembles, mais pas dans les deux. L’idée est la même que XOR : conserver ce qui diffère.
Si vous voulez une version plus explicite :
print(a.symmetric_difference(b))
Pour du code très lisible, symmetric_difference() peut être préférable. Pour du code concis, ^ est courant.
XOR et cryptographie : utile pour apprendre, pas pour sécuriser
XOR apparaît souvent dans les cours de cryptographie, car il permet de combiner une donnée avec une clé de manière réversible.
Exemple pédagogique avec des octets :
message = b"python"
cle = 0b01010101
chiffre = bytes(octet ^ cle for octet in message)
dechiffre = bytes(octet ^ cle for octet in chiffre)
print(chiffre)
print(dechiffre) # b'python'
Le même XOR appliqué deux fois avec la même clé revient au message initial.
Mais ce n’est pas une méthode de sécurité suffisante. Une clé courte, répétée ou prévisible se casse facilement. Pour un vrai besoin de chiffrement, utilisez une bibliothèque de cryptographie reconnue et un protocole adapté.
XOR reste en revanche excellent pour comprendre les opérations binaires, les masques et les propriétés réversibles.
Les erreurs fréquentes avec XOR en Python
Utiliser ^ pour une puissance
En Python, ^ ne calcule pas une puissance.
print(2 ^ 8) # 10
print(2 ** 8) # 256
Si vous venez d’un langage, d’une calculatrice ou d’un contexte mathématique où ^ signifie puissance, ce piège est très courant.
Mélanger logique booléenne et bitwise
Pour exprimer “au moins une condition”, utilisez or.
if age_majeur or autorisation_parentale:
print("Accès possible")
Pour exprimer “exactement une condition”, utilisez plutôt != entre booléens :
if age_majeur != autorisation_parentale:
print("Une seule condition est vraie")
L’opérateur ^ fonctionne, mais il est moins parlant pour beaucoup de lecteurs.
Appliquer XOR à des nombres décimaux
XOR fonctionne sur des entiers, pas sur des flottants.
print(5 ^ 3) # OK
print(5.0 ^ 3.0) # TypeError
Si vous manipulez des nombres décimaux, vous n’êtes probablement pas dans un usage bitwise.
Oublier les parenthèses dans les expressions
Les opérateurs bitwise ont leur propre priorité. Pour éviter les ambiguïtés, mettez des parenthèses dans les expressions non triviales.
resultat = (a & masque) ^ cle
C’est plus lisible que :
resultat = a & masque ^ cle
Même quand Python interprète correctement l’expression, le lecteur gagne du temps.
Manipuler des nombres négatifs sans masque
Avec les entiers négatifs, l’affichage binaire peut surprendre, car Python modélise les opérations bitwise comme si les entiers avaient une extension de signe.
print(-1 ^ 0b1111) # -16
Si vous voulez raisonner sur 8 bits, appliquez un masque :
resultat = (-1 ^ 0b1111) & 0xff
print(resultat) # 240
print(f"{resultat:08b}") # 11110000
Le masque force la lecture sur la largeur choisie.
operator.xor : la version fonction
Python expose aussi operator.xor, qui correspond à l’opérateur ^.
from operator import xor
print(xor(5, 3)) # 6
Cette fonction est surtout utile avec des outils comme reduce, map ou quand vous voulez passer l’opération en paramètre.
from functools import reduce
from operator import xor
valeurs = [1, 2, 3, 2, 1]
print(reduce(xor, valeurs)) # 3
Dans du code simple, a ^ b reste plus direct.
Petit mémo des cas d’usage
| Besoin | Forme Python recommandée |
|---|---|
| XOR bitwise entre entiers | a ^ b |
| XOR logique entre booléens | a != b |
| Fonction XOR réutilisable | operator.xor(a, b) |
| Trouver un élément unique avec des paires | boucle avec resultat ^= valeur |
| Basculer un bit | valeur ^ masque |
| Différence symétrique entre ensembles | a ^ b ou a.symmetric_difference(b) |
| Puissance | a ** b, jamais a ^ b |
Exercices rapides
Exercice 1
Prédisez le résultat :
print(7 ^ 3)
Correction :
print(f"{7:04b}") # 0111
print(f"{3:04b}") # 0011
print(f"{7 ^ 3:04b}") # 0100
print(7 ^ 3) # 4
Exercice 2
Complétez la valeur manquante :
a = 23
b = ... # à compléter
c = 31
# a ^ b == c
Correction :
a = 23
c = 31
b = a ^ c
print(b)
print(a ^ b == c) # True
Exercice 3
Retrouvez l’élément qui n’apparaît qu’une seule fois :
valeurs = [14, 8, 14, 3, 8, 21, 3]
Correction :
resultat = 0
for valeur in valeurs:
resultat ^= valeur
print(resultat) # 21
Pour aller plus loin
XOR est une petite opération, mais elle force à bien comprendre la différence entre logique booléenne, calcul binaire et opérateurs Python. C’est aussi un bon pont vers des sujets plus larges : masques, flags, chiffrement pédagogique, ensembles, complexité et algorithmes.
Pour continuer dans le même esprit :
- ROT13 en Python : encoder et décoder une chaîne simplement
- Modulo en Python : comprendre %, // et divmod avec exemples
- Complexité algorithmique en Python : comprendre O(n), O(log n) et O(n²)
La règle à retenir est simple : ^ sert au XOR, ** sert à la puissance, et a != b reste souvent la forme la plus lisible pour un XOR logique entre deux booléens.
Références
- Documentation Python officielle : opérateurs bitwise dans les expressions
- Documentation Python officielle : types numériques et opérations bitwise
- Documentation Python officielle :
operator.xor

