Adloun

La fonction hash donne l'entier à partir duquel le dictionnaire…

Exercice supplémentaire · niveau 3 (difficile) · NSI (première), chapitre 5 — Les dictionnaires · Sous le capot : le hachage

Énoncé

La fonction hash donne l'entier à partir duquel le dictionnaire calcule l'emplacement d'une clé. L'essayer sur un entier, un couple, un tableau, puis sur une chaîne — en relançant Python entre deux essais. Que constate-t-on ? Enfin, expliquer pourquoi {1: "a", True: "b"} n'a qu'une seule clé.

Corrigé


assert hash((1, 2)) == hash((1, 2))
assert hash(3) == 3 and hash(True) == 1

try:
    hash([1, 2])
except TypeError as e:
    assert str(e) == "unhashable type: 'list'"

try:
    hash((1, [2]))          # un p-uplet CONTENANT un tableau
    assert False, "aurait du echouer"
except TypeError:
    pass

Un p-uplet n'est immuable qu'en surface. (1, [2]) est un p-uplet, et pourtant il n'est pas hachable : la liste qu'il contient, elle, peut changer. La règle exacte n'est donc pas « les p-uplets sont des clés valides » mais « un p-uplet dont tous les éléments sont non modifiables l'est ». C'est le chapitre 4 poussé d'un cran.

La chaîne, d'une exécution à l'autre. En relançant Python trois fois :


hash("a")   #  389876162093088582
hash("a")   # -4050391632379907973
hash("a")   # -2929489315106233283

Le résultat change à chaque lancement. Python tire au démarrage une graine aléatoire pour le hachage des chaînes — une protection contre des attaques qui fabriqueraient exprès des clés entrant en collision. Conséquence directe, et elle valide l'avertissement du cours : l'ordre interne d'un dictionnaire n'est pas une propriété du programme. Ce qui est stable en Python depuis la version 3.7, c'est l'ordre d'insertion, pas l'ordre des emplacements calculés.

1 et True sont la même clé.


assert {1: "a", True: "b"} == {1: "b"}

Deux clés sont « la même » si elles sont égales et de même hachage. Or True == 1 et hash(True) == hash(1) : le dictionnaire n'y voit qu'une seule entrée, et la seconde écriture écrase la première. Le chapitre 2 disait que les booléens sont des entiers déguisés ; en voici la conséquence la plus surprenante.

Les autres exercices de ce chapitre Le cours du chapitre

Un blocage sur cet exercice ? Le tuteur d'Adloun guide par questions, sans donner la réponse.