web-dev-qa-db-fra.com

Itérer sur des dictionnaires en utilisant des boucles "pour"

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?

2804
TopChef

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()).

4946
sberry

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 pour for 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.

394
ars

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))
187
John La Rooy

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)
72
ssoler

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().

51
Alexander Gessler

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) .

27
chryss

Vous pouvez utiliser ceci:

for key,val in d.items():
    print key, 'is the key for ', val
16

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".

14
jdhao

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)
12
象嘉道

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']

Retourner aux dicts

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.

12
Aaron Hall

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)

CPython dictobject.c

7
abc

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;).

2
Neil Chowdhury o_O

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])
1
Amaan Durrani

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")

0
Joseph True