Passer au contenu principal
eLearner.app
Module 8 · Leçon 3 sur 431/36 dans le cours~12 min
Leçons du module (3/4)

collections : Counter et defaultdict

Le module collections ajoute des types de données spécialisés qui étendent les collections intégrées. Les trois plus utilisés : Counter, defaultdict, namedtuple.

Counter : comptage des fréquences

Python
from collections import Counter

parole = ["mela", "pera", "mela", "kiwi", "mela", "pera"]
c = Counter(parole)
# Counter({'mela': 3, 'pera': 2, 'kiwi': 1})

c["mela"]            # 3
c["banana"]          # 0   (default for missing keys, NO KeyError)
c.most_common(2)     # [('mela', 3), ('pera', 2)]

Il fonctionne également sur les chaînes (compte les caractères) :

Code
Counter("ciao mondo")
# Counter({'o': 2, 'c': 1, 'i': 1, 'a': 1, ' ': 1, 'm': 1, 'n': 1, 'd': 1})

Il prend en charge les opérations de type ensemble sur les nombres (+, -, &, |) — très pratique pour agréger les totaux provenant de différentes sources.

defaultdict : dictionnaire avec valeur par défaut automatique

Un dictionnaire qui, lorsque vous accédez à une clé manquante, la crée en appelant une fabrique.

Python
from collections import defaultdict

gruppi = defaultdict(list)        # factory = list (empty list)
for nome in ["Ada", "Linus", "Ada", "Grace"]:
    gruppi[nome].append(1)
# defaultdict(list, {'Ada': [1, 1], 'Linus': [1], 'Grace': [1]})

Sans defaultdict, vous devriez écrire :

Python
gruppi = {}
for nome in [...]:
    if nome not in gruppi:
        gruppi[nome] = []
    gruppi[nome].append(1)

Fabriques courantes : list, int (par défaut 0), set, dict.

namedtuple : tuples avec noms de champs

Un moyen léger de créer des classes d'enregistrements immuables. C'est un tuple, mais avec un accès aux champs par nom.

Python
from collections import namedtuple

Punto = namedtuple("Punto", ["x", "y"])
p = Punto(3, 4)
p.x          # 3 (access by name)
p[0]         # 3 (access by index, still a tuple)
p.x + p.y    # 7

# typical use: return multiple values from a function
def divisione(a, b):
    Risultato = namedtuple("Risultato", ["quoziente", "resto"])
    return Risultato(a // b, a % b)

r = divisione(17, 5)
r.quoziente   # 3
r.resto       # 2

(Pour des cas plus complexes, il existe également dataclasses depuis la version 3.7 — voir M9.)

namedtuple : enregistrements immuables légers

Le module collections exporte également namedtuple, qui vous permet de créer rapidement de légers objets similaires à des classes pour stocker des données structurées sans écrire de constructeurs ou de méthodes répétitives :

Python
from collections import namedtuple
Point = namedtuple('Point', ['x', 'y'])
p = Point(10, 20)
print(p.x, p.y)

À vous de jouer

Exercice#python.m8.l3.e1
Tentatives : 0Chargement…

Étant donné la liste `words = ['mela', 'pera', 'mela', 'kiwi', 'mela', 'pera']`, calculez le mot le plus fréquent sous forme de chaîne dans `top`. Évaluez `top`.

Chargement de l'éditeur…
Afficher l'indice

Counter(...).most_common(1) renvoie [(mot, compte)].

Solution disponible après 3 tentatives

Exercice de révision

Exercice#python.m8.l3.e2
Tentatives : 0Chargement…

Étant donné les étudiants `enrollments = [('Ada', 'mate'), ('Linus', 'fisica'), ('Ada', 'storia'), ('Grace', 'mate')]`, créez `courses_per_student` sous forme de defaultdict(list). Évaluez `dict(courses_per_student)`.

Chargement de l'éditeur…
Afficher l'indice

defaultdict(list) puis for s, c in enrollments.

Solution disponible après 3 tentatives

Défi supplémentaire

Exercice#python.m8.l3.e3
Tentatives : 0Chargement…

Importez `Counter` depuis `collections`. Comptez la fréquence des caractères dans la chaîne `text = "abracadabra"`. Stockez le compteur dans `char_counter` et évaluez-le.

Chargement de l'éditeur…
Afficher l'indice

Counter prend la chaîne en paramètre et compte les occurrences de chaque lettre.

Solution disponible après 3 tentatives