Les dictionnaires sont mis en œuvre comme les tables de hachage et il y a deux notions importantes lors de l'ajout de clés/valeurs de ici: de hachage et de l'égalité.
Pour insérer une clé/valeur, Python première calcule le hachage de la valeur de la clé. Cette valeur de hachage est utilisée pour déterminer la ligne de la table où Python doivent d'abord essayer de mettre la clé/valeur.
Si la ligne de la table de hachage est vide, grand: la nouvelle clé/valeur peut être insérée dans le dictionnaire, le remplissage de la ligne vide.
Cependant, si il y a déjà quelque chose dans cette ligne, Python a besoin de tester les clés pour l'égalité. Si les clés sont égaux (à l'aide d' ==
) alors qu'ils sont réputés être la même clé et Python juste besoin de mettre à jour la valeur correspondante sur la ligne.
(Si les touches ne sont pas égaux Python regarde les autres lignes dans la table jusqu'à ce qu'il trouve la clé ou atteint d'une ligne vide, mais ce n'est pas pertinent pour cette question.)
Lorsque vous écrivez {True: 'yes', 1: 'No'}
, vous dites Python pour créer un nouveau dictionnaire et le remplir avec deux paires clé/valeur. Ceux-ci sont traités de gauche à droite: True: 'yes'
alors 1: 'No'
.
Nous avons hash(True)
est égal à 1. La clé True
va à la ligne 1 dans la table de hachage et la chaîne 'yes'
valeur est sa valeur.
Pour la paire suivante, Python voit qu' hash(1)
est également 1 et ressemble tellement à la ligne 1 de la table. Il y a quelque chose de déjà là, alors maintenant, Python vérifie les clés de l'égalité. Nous avons 1 == True
donc 1
est réputée être la même clé que True
, et donc sa valeur correspondante est modifiée à la chaîne de caractères 'No'
.
Il en résulte un dictionnaire avec une entrée: {True: 'No'}
.
Si vous voulez à scruter les entrailles de Disponible 3.5 pour voir ce que la création d'un dictionnaire regarde en dessous de la surface-Python niveau, voici plus en détail.
Le code Python {True: 'yes', 1: 'No'}
est analysée en jetons, et donné pour le compilateur. Compte tenu de la syntaxe, Python sait qu'un dictionnaire doit être créée en utilisant les valeurs à l'intérieur des accolades. De Byte code pour charger les quatre valeurs sur la machine virtuelle de la pile (LOAD_CONST
), puis de construire le dictionnaire (BUILD_MAP
) est mis en attente.
-
Les quatre valeurs constantes sont poussées sur le haut de la pile dans l'ordre dans lequel ils sont vus:
'No'
1
'yes'
True
-
L'opcode BUILD_MAP
est alors appelée avec l'argument 2
(Python compté deux paires clé/valeur). Cet opcode est responsable de la création du dictionnaire à partir des éléments sur la pile. Il ressemble à ceci:
TARGET(BUILD_MAP) {
int i;
PyObject *map = _PyDict_NewPresized((Py_ssize_t)oparg);
if (map == NULL)
goto error;
for (i = oparg; i > 0; i--) {
int err;
PyObject *key = PEEK(2*i);
PyObject *value = PEEK(2*i - 1);
err = PyDict_SetItem(map, key, value);
if (err != 0) {
Py_DECREF(map);
goto error;
}
}
while (oparg--) {
Py_DECREF(POP());
Py_DECREF(POP());
}
PUSH(map);
DISPATCH();
}
Les trois étapes clés ici sont comme suit:
Une table de hachage vide est créé à l'aide d' _PyDict_NewPresized
. Petits dictionnaires (de seulement quelques éléments, comme les 2 dans ce cas) besoin d'une table avec huit lignes.
L' for
boucle est entré, à partir de 2 (dans ce cas) et le compte à rebours à 0. PEEK(n)
est une macro qui pointe vers le n-ième élément vers le bas de la pile. Par conséquent, à la première itération de la boucle, nous allons avoir
PyObject *key = PEEK(2*2); /* item 4 down the stack */
PyObject *value = PEEK(2*2 - 1); /* item 3 down the stack */
Cela signifie qu' *key
sera True
et *value
sera 'yes'
sur la première boucle à travers. Sur le second, il sera 1
et 'No'
.
-
PyDict_SetItem
est appelée à chaque tour de boucle pour mettre l' *key
et *value
dans le dictionnaire. C'est la même fonction qui est appelée lorsque vous écrivez dictionary[key] = value
. Il calcule le hachage de la clé de travail où regarder en premier dans la table de hachage, puis, si nécessaire, de comparer la clé de toutes les clés existant sur cette ligne (voir ci-dessus).