
Un ensemble (set) est une collection non ordonnée d'éléments uniques : il supprime automatiquement les doublons. C'est le quatrième type de collection natif de Python, aux côtés des listes, tuples et dictionnaires. Ce guide couvre la création d'un set, l'ajout et la suppression d'éléments, les opérations d'ensemble (union, intersection, différence), le test d'appartenance ultra-rapide, les set comprehensions et le frozenset.
Il s'adresse aux débutants qui veulent dédoublonner des données ou comparer des collections, et à celles et ceux qui cherchent des recherches performantes. Un set brille dès qu'on a besoin d'unicité ou de tester si une valeur est présente. Tous les exemples ont été exécutés avec Python 3.12.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Créer un ensemble et éviter le piège du set vide.
- Ajouter et supprimer des éléments proprement.
- Combiner des ensembles avec union, intersection et différence.
- Tester l'appartenance en temps constant, bien plus vite qu'une liste.
- Écrire une set comprehension et utiliser un frozenset.
Qu'est-ce qu'un ensemble
Section intitulée « Qu'est-ce qu'un ensemble »Un ensemble est une collection qui repose sur deux règles simples : ses éléments sont uniques (pas de doublon possible) et non ordonnés (aucune position, donc pas d'accès par index). Si vous ajoutez deux fois la même valeur, elle n'apparaît qu'une fois.
s = {1, 2, 3, 2, 1}print(s) # {1, 2, 3} → les doublons ont disparuCette structure vient tout droit des mathématiques. Elle est optimisée pour trois usages : éliminer les doublons, tester très vite si une valeur est présente, et réaliser des opérations d'ensemble comme l'union ou l'intersection. Seule contrainte : un set ne peut contenir que des éléments hashables (nombres, chaînes, tuples), pas des listes ni des dictionnaires.
Créer un ensemble
Section intitulée « Créer un ensemble »On crée un set avec des accolades {} ou avec la fonction set(). Attention à un piège classique : des accolades vides créent un dictionnaire, pas un ensemble.
fruits = {"pomme", "banane", "cerise"} # set littéralvide = set() # ensemble vide
faux_set = {} # ATTENTION : c'est un dict vide !print(type(faux_set)) # <class 'dict'>On crée souvent un set à partir d'une liste, ce qui la dédoublonne au passage :
notes = [12, 15, 12, 18, 15]uniques = set(notes)print(uniques) # {18, 12, 15}Ajouter et supprimer des éléments
Section intitulée « Ajouter et supprimer des éléments »Un set est modifiable. On ajoute avec add() et on retire avec discard() ou remove(). La différence entre les deux compte :
couleurs = {"rouge", "vert"}
couleurs.add("bleu") # {'rouge', 'vert', 'bleu'}couleurs.discard("jaune") # absent : ne fait rien, aucune erreurcouleurs.remove("vert") # présent : retiré# couleurs.remove("jaune") # absent : lève KeyErrordiscard()ne lève jamais d'erreur si l'élément est absent : c'est le choix sûr.remove()lèveKeyErrorsi l'élément n'existe pas.pop()retire un élément arbitraire (l'ordre n'étant pas défini), etclear()vide le set.
Les opérations d'ensemble
Section intitulée « Les opérations d'ensemble »C'est la vraie force des sets : combiner deux collections avec les opérateurs mathématiques. Chaque opérateur a une méthode équivalente, plus lisible pour les débutants.
a = {1, 2, 3, 4}b = {3, 4, 5, 6}
print(a | b) # union : {1, 2, 3, 4, 5, 6} (a.union(b))print(a & b) # intersection : {3, 4} (a.intersection(b))print(a - b) # différence : {1, 2} (a.difference(b))print(a ^ b) # différence symétrique : {1, 2, 5, 6}Voici comment lire chaque opération :
| Opérateur | Méthode | Résultat | Signification |
|---|---|---|---|
a | b | union | tous les éléments | dans a ou b |
a & b | intersection | éléments communs | dans a et b |
a - b | difference | propres à a | dans a mais pas b |
a ^ b | symmetric_difference | non partagés | dans l'un ou l'autre, pas les deux |
On compare aussi deux ensembles avec <= (sous-ensemble) et >= (surensemble) :
print({1, 2} <= a) # True : {1, 2} est inclus dans aprint(a.isdisjoint({9})) # True : aucun élément communCas concret : comparer deux listes
Section intitulée « Cas concret : comparer deux listes »Ces opérations répondent à une question fréquente : qu'est-ce qui a changé entre deux collections ?
serveurs_avant = {"web-1", "web-2", "db-1"}serveurs_apres = {"web-1", "web-3", "db-1", "db-2"}
ajoutes = serveurs_apres - serveurs_avant # {'web-3', 'db-2'}supprimes = serveurs_avant - serveurs_apres # {'web-2'}communs = serveurs_avant & serveurs_apres # {'web-1', 'db-1'}En trois lignes, on obtient ce qui a été ajouté, supprimé et conservé, sans écrire une seule boucle.
Appartenance : le vrai atout des sets
Section intitulée « Appartenance : le vrai atout des sets »Tester si une valeur est présente avec in est extrêmement rapide sur un set : le temps est en moyenne constant (noté O(1)), quel que soit le nombre d'éléments. Sur une liste, la même opération parcourt les éléments un par un (O(n)).
import timeit
gros_set = set(range(100_000))grosse_liste = list(range(100_000))
t_set = timeit.timeit(lambda: 99_999 in gros_set, number=1000)t_list = timeit.timeit(lambda: 99_999 in grosse_liste, number=1000)
print(f"in set : {t_set:.5f}s") # ~0.00003 sprint(f"in liste : {t_list:.5f}s") # ~0.43 sSur cet exemple, chercher dans un set est plus de 10 000 fois plus rapide que dans une liste. Dès que vous testez souvent l'appartenance à une grande collection, un set est le bon réflexe.
Les set comprehensions
Section intitulée « Les set comprehensions »Comme les listes et les dictionnaires, les ensembles ont leur comprehension : la même syntaxe, mais entre accolades, avec dédoublonnage automatique.
mots = ["chat", "chien", "chat", "oiseau"]initiales = {mot[0] for mot in mots}print(initiales) # {'c', 'o'} → une seule fois chaque initialeL'expression {expression for element in iterable} construit un set en appliquant l'expression à chaque élément, tout en garantissant l'unicité du résultat.
frozenset : l'ensemble immuable
Section intitulée « frozenset : l'ensemble immuable »Le frozenset est la version immuable du set : une fois créé, on ne peut plus le modifier. En échange, il devient hashable, ce qui permet de l'utiliser comme clé de dictionnaire ou comme élément d'un autre set, chose impossible avec un set normal.
fs = frozenset([1, 2, 3])# fs.add(4) -> AttributeError : frozenset est figé
# utilisable comme clé de dictionnaireresultats = {frozenset(["a", "b"]): "paire AB"}print(resultats[frozenset(["b", "a"])]) # 'paire AB'C'est utile pour représenter des combinaisons figées (un couple de tags, un ensemble de permissions) que l'on veut indexer ou stocker.
À retenir
Section intitulée « À retenir »- Un
setest une collection non ordonnée d'éléments uniques : il supprime les doublons. - Le set vide s'écrit
set(), jamais{}(qui crée un dictionnaire). - On ajoute avec
add, on retire avecdiscard(sûr) ouremove(lèveKeyErrorsi absent). - Les opérations d'ensemble (
|,&,-,^) comparent deux collections sans boucle. - Le test
inest en temps constant sur un set, des milliers de fois plus rapide que sur une liste. - La set comprehension
{x for x in ...}construit un set en dédoublonnant. - Le
frozensetest immuable et hashable : utilisable comme clé de dict ou élément de set. - Les éléments d'un set doivent être hashables : ni liste, ni dict à l'intérieur.
FAQ : les ensembles en Python
Section intitulée « FAQ : les ensembles en Python »s = {1, 2, 3, 2, 1}
print(s) # {1, 2, 3}
Ses éléments doivent être hashables (nombres, chaînes, tuples), et l'ordre n'est pas garanti. On l'utilise surtout pour :- dédoublonner une collection,
- tester une appartenance très vite (
in), - faire des opérations d'ensemble (union, intersection).
set(), surtout pas {} :vide = set() # ensemble vide
faux = {} # ATTENTION : c'est un dictionnaire vide !
print(type(faux)) # <class 'dict'>
C'est le piège classique : {} est réservé au dictionnaire. Pour un set vide, seul set() fonctionne. On le remplit ensuite avec add(), ou on le crée depuis une liste :s = set([1, 2, 2, 3]) # {1, 2, 3}
noms = ["alice", "bob", "alice", "eve"]
uniques = list(set(noms)) # doublons supprimés
Attention : set ne conserve pas l'ordre. Pour garder l'ordre d'apparition, utilisez plutôt :uniques = list(dict.fromkeys(noms)) # ['alice', 'bob', 'eve']
dict.fromkeys déduplique tout en préservant la séquence, car les dictionnaires conservent l'ordre depuis Python 3.7.a = {1, 2, 3, 4}
b = {3, 4, 5, 6}
a | b # union : {1, 2, 3, 4, 5, 6}
a & b # intersection : {3, 4}
a - b # différence : {1, 2}
a ^ b # différence symétrique : {1, 2, 5, 6}
Chaque opérateur a une méthode équivalente (a.union(b), a.intersection(b)...). On compare aussi avec <= (sous-ensemble) et >= (surensemble).setest modifiable (add,remove).frozensetest sa version immuable : figé après création.
fs = frozenset([1, 2, 3])
# fs.add(4) -> AttributeError
Comme il est immuable, le frozenset est hashable, donc utilisable comme clé de dictionnaire ou élément d'un autre set, ce qu'un set normal ne permet pas :cache = {frozenset([1, 2]): "resultat"}
- les éléments doivent être uniques,
- vous testez souvent l'appartenance (
in), - vous faites des opérations d'ensemble.
in est décisive : il est en moyenne en temps constant (O(1)) sur un set, contre un parcours complet (O(n)) sur une liste. Sur 100 000 éléments, l'écart dépasse un facteur 10 000.Gardez la liste si l'ordre ou les doublons comptent, ou s'il vous faut l'accès par index.Prochaines étapes
Section intitulée « Prochaines étapes »Les ensembles complètent les autres collections natives. Voici les sujets qui s'y rattachent directement.