Je suis un peu perplexe par le code suivant:
d = {'x': 1, 'y': 2, 'z': 3}
for key in d:
print key, 'corresponds to', d[key]
Ce que je ne comprends pas, c’est la partie key
. Comment Python reconnaît-il qu'il suffit de lire la clé du dictionnaire? Est-ce que key
est un mot spécial en Python? Ou est-ce simplement une variable?
key
est juste un nom de variable.
for key in d:
passera simplement sur les clés du dictionnaire plutôt que sur les clés et les valeurs. Pour boucler sur la clé et la valeur, vous pouvez utiliser les éléments suivants:
Pour Python 2.x:
for key, value in d.iteritems():
Pour Python 3.x:
for key, value in d.items():
Pour tester vous-même, changez le mot key
en poop
.
Pour Python 3.x, iteritems()
a été remplacé par simplement items()
, qui renvoie une vue similaire à un jeu, telle que iteritems()
, mais encore mieux. Ceci est également disponible dans la version 2.7 en tant que viewitems()
.
L'opération items()
fonctionnera à la fois pour 2 et 3, mais en 2 elle retournera une liste des paires (key, value)
du dictionnaire, qui ne reflétera pas les modifications apportées à la dict après la items()
. appel. Si vous voulez le comportement 2.x dans 3.x, vous pouvez appeler list(d.items())
.
Ce n'est pas que la clé est un mot spécial, mais que les dictionnaires implémentent le protocole itérateur. Vous pouvez le faire dans votre classe, par exemple voir cette question pour savoir comment construire des itérateurs de classe.
Dans le cas des dictionnaires, il est implémenté au niveau C. Les détails sont disponibles dans PEP 234 . En particulier, la section intitulée "Dictionnaire des itérateurs":
Les dictionnaires implémentent un emplacement tp_iter qui renvoie un itérateur efficace qui parcourt les clés du dictionnaire. [...] Cela signifie que nous pouvons écrire
for k in dict: ...
qui est équivalent à, mais beaucoup plus rapide que
for k in dict.keys(): ...
tant que la restriction sur les modifications du dictionnaire (par la boucle ou par un autre thread) n'est pas violée.
Ajoutez des méthodes aux dictionnaires qui renvoient explicitement différents types d'itérateurs:
for key in dict.iterkeys(): ... for value in dict.itervalues(): ... for key, value in dict.iteritems(): ...
Cela signifie que
for x in dict
est un raccourci pourfor x in dict.iterkeys()
.
Dans Python 3, dict.iterkeys()
, dict.itervalues()
et dict.iteritems()
ne sont plus pris en charge. Utilisez dict.keys()
, dict.values()
et dict.items()
à la place.
Itérer sur une dict
itère à travers ses clés sans ordre particulier, comme vous pouvez le voir ici:
Edit: (Ceci est n'est plus le cas dans Python3.6, mais notez que c'est pas encore garanti comportement
>>> d = {'x': 1, 'y': 2, 'z': 3}
>>> list(d)
['y', 'x', 'z']
>>> d.keys()
['y', 'x', 'z']
Pour votre exemple, il vaut mieux utiliser dict.items()
:
>>> d.items()
[('y', 2), ('x', 1), ('z', 3)]
Cela vous donne une liste de tuples. Lorsque vous les survolez ainsi, chaque tuple est décompressé automatiquement dans k
et v
:
for k,v in d.items():
print(k, 'corresponds to', v)
Utiliser k
et v
comme noms de variable lors de la lecture d'une boucle sur dict
est assez courant si le corps de la boucle ne contient que quelques lignes. Pour des boucles plus complexes, il peut être judicieux d'utiliser des noms plus descriptifs:
for letter, number in d.items():
print(letter, 'corresponds to', number)
C'est une bonne idée de prendre l'habitude d'utiliser des chaînes de format:
for letter, number in d.items():
print('{0} corresponds to {1}'.format(letter, number))
key
est simplement une variable.
Pour Python2.X:
d = {'x': 1, 'y': 2, 'z': 3}
for my_var in d:
print my_var, 'corresponds to', d[my_var]
... ou mieux,
d = {'x': 1, 'y': 2, 'z': 3}
for the_key, the_value in d.iteritems():
print the_key, 'corresponds to', the_value
Pour Python3.X:
d = {'x': 1, 'y': 2, 'z': 3}
for the_key, the_value in d.items():
print(the_key, 'corresponds to', the_value)
Lorsque vous parcourez des dictionnaires à l'aide de la syntaxe for .. in ..
-, il effectue toujours une itération sur les clés (les valeurs sont accessibles à l'aide de dictionary[key]
).
Pour parcourir les paires clé-valeur, utilisez for k,v in s.iteritems()
dans Python 2 et Python 3 for k,v in s.items()
.
Ceci est un idiome de boucle très commun. in
est un opérateur. Pour savoir quand utiliser for key in dict
et quand il doit s'agir de for key in dict.keys()
, voyez article idiomatique de David Goodger Python (copie archivée) .
Vous pouvez utiliser ceci:
for key,val in d.items():
print key, 'is the key for ', val
J'ai un cas d'utilisation où je dois parcourir le dict pour obtenir la paire clé, valeur, ainsi que l'index indiquant où je suis. Voici comment je le fais:
d = {'x': 1, 'y': 2, 'z': 3}
for i, (key, value) in enumerate(d.items()):
print(i, key, value)
Notez que les parenthèses autour de la clé, la valeur est importante, sans les parenthèses, vous obtenez une valeur ValueError "pas assez de valeurs pour décompresser".
quoi que, aujourd'hui, les deux python 2.6 et 2.7, ainsi que 3.x, dans ma boîte fonctionnent bien avec items()
:
z = {0: 'a', 1: 'b'}
for k, v in z.items(): print(v, k)
Itérer sur des dictionnaires en utilisant des boucles 'pour'
d = {'x': 1, 'y': 2, 'z': 3} for key in d: ...
Comment Python reconnaît-il qu'il suffit de lire la clé du dictionnaire? La clé est-elle un mot spécial en Python? Ou est-ce simplement une variable?
Ce n'est pas juste for
boucles. La Parole importante ici est "itérative".
Un dictionnaire est un mappage de clés en valeurs:
d = {'x': 1, 'y': 2, 'z': 3}
Chaque fois que nous itérons dessus, nous itérons sur les clés. Le nom de la variable key
est uniquement destiné à être descriptif - et il convient parfaitement.
Cela se passe dans une compréhension de liste:
>>> [k for k in d]
['x', 'y', 'z']
Cela arrive quand on passe le dictionnaire à lister (ou tout autre objet de type collection):
>>> list(d)
['x', 'y', 'z']
La manière dont Python itère est, dans un contexte où cela est nécessaire, elle appelle la méthode __iter__
de l'objet (dans ce cas le dictionnaire) qui renvoie un itérateur (dans ce cas, un keyiterator). objet):
>>> d.__iter__()
<dict_keyiterator object at 0x7fb1747bee08>
Nous ne devrions pas utiliser ces méthodes spéciales nous-mêmes, mais plutôt utiliser la fonction intégrée respective pour l'appeler, iter
:
>>> key_iterator = iter(d)
>>> key_iterator
<dict_keyiterator object at 0x7fb172fa9188>
Les itérateurs ont une méthode __next__
, mais nous l'appelons avec la fonction intégrée, next
:
>>> next(key_iterator)
'x'
>>> next(key_iterator)
'y'
>>> next(key_iterator)
'z'
>>> next(key_iterator)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
Lorsqu'un itérateur est épuisé, il soulève StopIteration
. C’est ainsi que Python sait comment quitter une boucle for
, une liste de compréhension, une expression génératrice ou tout autre contexte itératif. Une fois qu'un itérateur lève StopIteration
, il le liera toujours - si vous voulez effectuer une nouvelle itération, vous en avez besoin d'un nouveau.
>>> list(key_iterator)
[]
>>> new_key_iterator = iter(d)
>>> list(new_key_iterator)
['x', 'y', 'z']
Nous avons vu les dictés itérer dans de nombreux contextes. Ce que nous avons vu, c’est que chaque fois que nous parcourons un dict, nous obtenons les clés. Retour à l'exemple d'origine:
d = {'x': 1, 'y': 2, 'z': 3} for key in d:
Si nous changeons le nom de la variable, nous obtenons toujours les clés. Essayons:
>>> for each_key in d:
... print(each_key, '=>', d[each_key])
...
x => 1
y => 2
z => 3
Si nous voulons parcourir les valeurs, nous devons utiliser la méthode .values
de dicts, ou pour les deux ensemble, .items
:
>>> list(d.values())
[1, 2, 3]
>>> list(d.items())
[('x', 1), ('y', 2), ('z', 3)]
Dans l'exemple donné, il serait plus efficace de parcourir les éléments suivants:
for a_key, corresponding_value in d.items():
print(a_key, corresponding_value)
Mais à des fins académiques, l'exemple de la question est très bien.
Vous pouvez vérifier l'implémentation de dicttype
de CPython sur GitHub. C'est la signature de la méthode qui implémente l'itérateur de dict:
_PyDict_Next(PyObject *op, Py_ssize_t *ppos, PyObject **pkey,
PyObject **pvalue, Py_hash_t *phash)
Pour parcourir les touches, il est plus lent mais mieux vaut utiliser my_dict.keys()
. Si vous avez essayé de faire quelque chose comme ça:
for key in my_dict:
my_dict[key+"-1"] = my_dict[key]-1
cela créerait une erreur d'exécution parce que vous modifiez les clés pendant l'exécution du programme. Si vous êtes absolument prêt à réduire le temps, utilisez la méthode for key in my_dict
, mais vous en avez été averti;).
Pour key dans my_dict est en réalité égal à for key dans my_dict.keys (). Donc, si vous voulez obtenir des valeurs de dict, vous pouvez essayer deux méthodes.
Un:
for value in my_dict.values():
print(value)
Deux:
for key in my_dict:
print(my_dict[key])
Suggestion d'impression pour les valeurs longues
Si vous avez de longues chaînes dans les valeurs, voici un moyen rapide de l’afficher dans un format lisible (plus?):for key, value in my_dictionary.iteritems(): print(key) print("---------") print(value) print("\n")