Apprenez en lisant dans l'ordre

collections — Counter / defaultdict / deque / namedtuple

Counter pour compter les occurrences, defaultdict pour les clés manquantes, deque pour des opérations O(1) aux deux bouts et un buffer circulaire, et namedtuple pour des enregistrements nommés.

Le module collections regroupe des structures de données spécialisées qui comblent les manques laissés par list / dict / tuple. Cet article passe en revue les quatre que tu utiliseras le plus souvent dans des projets réels : Counter / defaultdict / deque / namedtuple, dans cet ordre.

À quoi sert chacune des quatre

Chacune existe pour simplifier un cas pénible à écrire avec les types intégrés simples. Le tableau ci-dessous donne la vue d'ensemble, puis chaque section plonge dans son utilisation.

Les quatre types de collections
CounterCompter les occurrencesdefaultdictInit auto des clés manquantesdequeO(1) aux deux extrémitésnamedtupleNommer les champs du tuple
Counter sert au comptage, defaultdict gère les clés manquantes, deque offre des opérations rapides aux deux extrémités, et namedtuple ajoute des noms aux tuples. Les quatre sont des types d'extension qui ajoutent du confort par-dessus list / dict / tuple simples.
TypeProblème qu'il résoutAlternative simple
CounterCompter les éléments un par un avec une boucle est verbeuxfor + dict pour compter
defaultdictBesoin de if x not in d: d[x] = ... avant d'utiliser une nouvelle clédict.setdefault(...)
dequelist.insert(0, ...) et list.pop(0) sont lents (O(n))list (ok pour de petites données)
namedtupleLes éléments d'un tuple ne sont accessibles que par positiondataclass ou dict (plus lourd)

Counter — compter les occurrences en une ligne

Counter est une classe qui prend un itérable (une list, une chaîne, etc.) et retourne un dict du nombre de fois où chaque élément apparaît. Avec un dict simple, tu écrirais une boucle qui vérifie si la clé existe déjà, l'initialise à 1 sinon, ou l'incrémente sinon — mais Counter fait le même travail en une ligne : Counter(list).

La valeur retournée est une sous-classe de dict, donc tu peux extraire les valeurs avec counter["apple"] exactement comme un dict normal. Il y a aussi .most_common(N), qui retourne une liste de tuples (élément, compte) dans l'ordre décroissant — parfait pour les classements.

Comment Counter fonctionne
List[apple, banana, apple, ...]Counter(list)Counter{apple: 3, banana: 2, ...}compter
Passe simplement un itérable et tu récupères un sous-dict avec le nombre d'occurrences par élément. most_common(N) retourne le top N par fréquence, donc tu peux écrire un classement en une ligne.

Compte six enregistrements d'achat par produit avec Counter. Sens comment une seule ligne remplace une boucle for classique.

① Importe Counter depuis collections

② Définis la liste d'achats ["apple", "banana", "apple", "cherry", "banana", "apple"]

③ Passe la liste à Counter pour construire le comptage et affiche-le sous la forme Nombre : ◯

④ Affiche le compte de apple sous la forme Nombre de apple : ◯ (tu peux utiliser le même accès par crochets que dict)

⑤ Utilise most_common pour récupérer le top 2 et affiche-le sous la forme Top 2 : ◯

(Si ton code s'exécute correctement, l'explication apparaîtra.)

Éditeur Python

Exécuter le code pour voir le résultat

defaultdict — initialiser automatiquement les clés manquantes

defaultdict est un dict qui insère automatiquement une valeur par défaut quand tu accèdes à une clé qui n'existe pas encore. Avec un dict simple, tu dois écrire la danse vérification d'existence + initialisation à chaque fois, comme if key not in d: d[key] = []. Avec defaultdict, tu passes une fonction qui produit la valeur initiale au moment de la création, et il appelle cette fonction automatiquement la première fois qu'on touche une clé manquante.

Les deux motifs que tu verras le plus sont defaultdict(list) (liste vide pour les clés manquantes) et defaultdict(int) (0 pour les clés manquantes). L'argument est une fonction qui retourne la valeur initiale quand elle est appelée sans argumentslist et int correspondent tous les deux (ils retournent [] et 0 respectivement), donc tu les passes directement.

dict vs defaultdict
dict simpled["x"] (pas de clé)→ KeyErrorBesoin :if x not in d: d[x] = []defaultdict(list)d["x"] (pas de clé)→ Crée auto []Appelle .append(...)directement
Un dict simple lève KeyError sur les clés manquantes. defaultdict appelle la fonction passée à la construction et utilise le résultat. Passe list pour une liste vide, int pour 0, set pour un set vide.

Quand choisir Counter vs defaultdict

Si tu veux juste compter des choses, Counter est plus concis (et tu obtiens most_common gratuitement). Si tu regroupes en listes ou en sets — tout cas où la valeur initiale est un conteneur videdefaultdict(list) / defaultdict(set) est le meilleur choix.

Regroupe des fruits par couleur. Avec defaultdict(list), la première fois que tu touches une clé de couleur, il crée automatiquement une liste vide, donc tu peux appeler .append sans vérification d'existence.

① Importe defaultdict depuis collections

② Crée un defaultdict dont la valeur par défaut est une liste vide

③ Enregistre ces trois entrées dans l'ordre :

- "red""apple"

- "yellow""banana"

- "red""cherry"

Convertis en dict normal et affiche sous la forme Par couleur : ◯ (afficher directement le defaultdict donne une représentation moins lisible)

Éditeur Python

Exécuter le code pour voir le résultat

deque — opérations en O(1) aux deux extrémités

deque (double-ended queue, file à double extrémité) est une structure de données semblable à list qui supporte l'ajout et le retrait aux deux extrémités. La list simple gère déjà les opérations à droite via append et pop, mais list.insert(0, x) et list.pop(0) décalent chaque élément d'une case en interne, donc elles finissent en O(n) (plus lentes à mesure que la liste grandit).

deque est conçu pour que les deux extrémités soient en O(1) (temps constant indépendamment de la longueur), ce qui en fait le bon choix pour les files, les buffers d'historique et garder les N entrées les plus récentes — partout où tu dois pousser et retirer des deux côtés. L'argument maxlen est particulièrement pratique : fixe une longueur max, et les ajouts au-delà de cette limite suppriment silencieusement l'élément à l'extrémité opposée, te donnant un buffer circulaire gratuitement.

Coût des opérations list vs deque
listAjout / retrait à gaucheDécale chaque élémentd'une case→ O(n) lentdequeappend / pop aux 2 extrémitésManipulation de pointeursuniquement→ O(1) rapide
Les opérations à gauche de list sont en O(n) (chaque élément se décale), tandis que deque est en O(1) aux deux extrémités. Avec deque(maxlen=N), tu obtiens un buffer circulaire qui retire automatiquement le plus ancien quand il est plein.
MéthodeEffetCoût
append(x)Ajoute à droiteO(1)
appendleft(x)Ajoute à gaucheO(1)
pop()Retire à droiteO(1)
popleft()Retire à gaucheO(1)
maxlen=NFixe la longueur max (buffer circulaire)L'extrémité opposée est supprimée automatiquement
Méthodes principales de deque
appendleft(x)deque[a, b, c]append(x)popleft()pop()
Sur le deque central, l'extrémité gauche utilise appendleft / popleft et l'extrémité droite utilise append / pop. Le sens des flèches montre ajout (vers le deque) vs retrait (depuis le deque).

Garde les 3 derniers logs d'accès dans un deque(maxlen=3). Après 5 ajouts, seuls les 3 derniers survivent.

① Importe deque depuis collections

② Crée un deque vide avec une longueur max de 3

Ajoute les entiers 0 à 4 dans l'ordre (5 au total)

④ Affiche le résultat sous la forme 3 derniers : ◯ (les anciens 0 et 1 doivent avoir été poussés dehors)

Éditeur Python

Exécuter le code pour voir le résultat

Retire la tête et la queue d'une file de tâches. Utilise popleft et pop pour changer l'extrémité d'où tu retires.

① Importe deque depuis collections

② Construis un deque à partir des quatre tâches ["Tâche A", "Tâche B", "Tâche C", "Tâche D"]

③ Utilise popleft() pour récupérer la première tâche et affiche-la sous la forme Première tâche : ◯

④ Utilise pop() pour récupérer la dernière tâche et affiche-la sous la forme Dernière tâche : ◯

⑤ Affiche le deque restant sous la forme Restant : ◯

Éditeur Python

Exécuter le code pour voir le résultat

namedtuple — enregistrements légers qui nomment les champs du tuple

namedtuple est une fonction qui définit un tuple à champs nommés en une ligne. Un tuple simple comme (3, 4) n'est accessible que par position (p[0] / p[1]), donc le lecteur doit se rappeler quel emplacement est lequel. namedtuple te permet d'écrire p.x / p.y avec des noms parlants, ce qui est un grand gain de lisibilité.

Il reste compatible avec les tuples normaux — l'indexation p[0] et le dépaquetage *p fonctionnent toujours — donc tu peux ajouter des noms à du code existant basé sur tuple sans rien casser. C'est une extension légère.

namedtuple en un coup d'œil
Point = namedtuple('Point', ['x', 'y'])p = Point(3, 4)Par nomp.x / p.yPar indexp[0] / p[1]En dictp._asdict()
Définit un équivalent de classe en une ligne, puis utilise à la fois l'accès positionnel (p[0]) et l'accès nommé (p.x). _asdict() convertit en dict, ce qui s'intègre bien avec JSON et pprint.

namedtuple vs dataclass

Si tu as juste besoin d'un enregistrement léger immuable, opte pour namedtuple. Si tu veux des méthodes, des valeurs par défaut et des annotations de type détaillées, dataclass (couvert dans deux articles) est le bon outil. La force de namedtuple est la compatibilité tuple — il est parfait pour remplacer des types de retour existants comme def f() -> tuple[int, int]: sans casser les appelants.

Définis un namedtuple Point et lis les coordonnées par nom.

① Importe namedtuple depuis collections et crées-en un avec le nom de classe "Point" et les champs ["x", "y"]

② Construis une instance p avec x=3, y=4

③ Affiche sous la forme x: 3 y: 4 en utilisant l'accès nommé p.x et p.y

Éditeur Python

Exécuter le code pour voir le résultat

Extras de namedtuple — repr / index / _asdict

En plus de l'accès nommé style classe, namedtuple te donne l'accès par index compatible tuple, un repr lisible, et une méthode _asdict pour la conversion en dict. Tu utiliseras ceux-ci pour le débogage, la compatibilité avec des API existantes et la sérialisation JSON, entre autres.

Reprends le p de la Pratique 1 et essaie les trois motifs d'accès supplémentaires.

print("repr:", p) pour afficher sous la forme repr: Point(x=3, y=4)

② Utilise p[0] et p[1] pour l'accès par index et affiche sous la forme Par index: 3 4

③ Utilise p._asdict() pour afficher sous la forme En dict: {'x': 3, 'y': 4}

Éditeur Python

Exécuter le code pour voir le résultat
QUIZ

Vérification des connaissances

Répondez à chaque question une par une.

Question 1Quelle est la façon la plus concise d'obtenir le compte d'occurrences par élément d'une liste nums en une ligne ?

Question 2Après avoir créé defaultdict(list), que te donne le premier accès à une nouvelle clé d["x"] ?

Question 3Lequel correspond le mieux quand tu veux garder seulement les 5 éléments les plus récents ?