Dictionnaires et état indexé par clés
Un dict associe des clés uniques et hachables à des valeurs. Il est mutable et préserve l'ordre d'insertion, qui n'est toutefois pas un ordre trié.
counts = {"jpg": 10, "csv": 2}
counts["csv"] += 1
counts["txt"] = 4
Contrats de recherche
Choisissez l'opération selon la manière dont l'absence doit être traitée :
required = config["region"] # KeyError si absent
optional = config.get("timeout", 30) # valeur par défaut si absent
if "token" in config: # l'appartenance teste les clés
use(config["token"])
get ne distingue pas une clé absente d'une clé présente dont la valeur est égale à celle par défaut. Utilisez un test d'appartenance ou une sentinelle privée lorsque cette distinction compte.
Pour les accumulations, collections.defaultdict et collections.Counter expriment souvent mieux l'intention que des appels répétés à setdefault.
Clés et hachage
Les clés doivent être hachables. Les chaînes, les nombres et les tuples de valeurs hachables le sont souvent ; les listes et dictionnaires ne le sont pas. Deux objets égaux doivent avoir le même hachage. Modifier les données qui participent à l'égalité ou au hachage après avoir utilisé un objet comme clé peut rendre l'association logiquement incohérente.
Préférez des identifiants métier dotés d'une égalité stable. N'utilisez pas un conteneur mutable uniquement parce qu'il peut être enveloppé dans une implémentation personnalisée du hachage.
Itération et vues
for key in mapping:
...
for key, value in mapping.items():
...
keys = mapping.keys() # vue dynamique, pas une liste copiée
values = mapping.values()
Changer la taille du dictionnaire pendant l'itération sur une vue peut lever une erreur ou omettre du travail. Parcourez list(mapping.items()) lorsqu'un instantané est requis.
Mise à jour et fusion
update modifie le récepteur. L'opérateur | crée un nouveau dictionnaire. Dans les deux cas, les valeurs de droite l'emportent quand les clés se chevauchent.
effective = defaults | overrides
defaults.update(overrides)
Ces opérations sont superficielles : les associations imbriquées sont remplacées, pas fusionnées récursivement. Définissez une politique explicite pour les fusions profondes de configuration.
Dans l'implémentation par table de hachage de CPython, en supposant un hachage et des tests d'égalité de coût constant, la recherche, l'insertion et la suppression sont généralement en en moyenne, sans garantie absolue de temps constant dans le pire cas. L'itération est en .
Clés égales, ordre et valeurs indépendantes
Le contrat des dictionnaires
garantit l'ordre d'insertion depuis Python 3.7. Modifier une valeur ne déplace
pas sa clé ; la supprimer puis la réinsérer la place en dernier. L'égalité compare
les paires clé/valeur, pas l'ordre d'insertion. Des clés numériques égales comme
1, 1.0 et True désignent la même entrée.
mapping = {1: "integer", True: "boolean", 1.0: "float"}
assert len(mapping) == 1
assert mapping[1] == "float"
ordered = {"a": 1, "b": 2}
ordered["a"] = 3
assert list(ordered) == ["a", "b"]
assert ordered.pop("a") == 3
ordered["a"] = 4
assert list(ordered) == ["b", "a"]
assert ordered == {"a": 4, "b": 2}
shared = dict.fromkeys(["a", "b"], [])
shared["a"].append(1)
assert shared["b"] == [1]
separate = {key: [] for key in ["a", "b"]}
separate["a"].append(1)
assert separate["b"] == []
fromkeys réutilise la même valeur fournie pour chaque clé ; une compréhension
évalue son expression de valeur pour chaque entrée. Le hachage doit rester stable
durant la vie de l'objet. Des hachages égaux ne prouvent pas l'égalité des clés :
les collisions sont résolues par des tests d'égalité. Un tuple contenant une liste
n'est pas hachable. del mapping[key] et pop(key) lèvent KeyError en cas
d'absence ; pop(key, default) renvoie la valeur par défaut. Comme pour get,
l'expression par défaut est évaluée avant l'appel, même si la clé existe.