Question Itérer sur les dictionnaires à l'aide de boucles "for"


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 le key portion. Comment Python reconnaît-il qu'il lui suffit de lire la clé du dictionnaire? Est key un mot spécial en Python? Ou est-ce simplement une variable?


2105
2017-07-20 22:27


origine


Réponses:


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 faire une boucle 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 par vous-même, changez le mot key à poop.

Pour Python 3.x, iteritems() a été remplacé avec simplement items(), qui renvoie une vue de type soutenu par la dict, comme iteritems() mais encore mieux. Ceci est également disponible en 2.7 comme viewitems().

L'opération items() travaillera à la fois pour 2 et 3, mais dans 2 il retournera une liste des dictionnaires (key, value) paires, qui ne reflètent pas les changements à la dict qui se produisent après la items() appel. Si vous voulez le comportement 2.x dans 3.x, vous pouvez appeler list(d.items()).


3784
2017-07-20 22:29



Ce n'est pas que la clé est un mot spécial, mais que les dictionnaires implémentent le protocole d'itérateur. Vous pourriez le faire dans votre classe, par ex. 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 "Dictionary Iterators":

  • Les dictionnaires implémentent un emplacement tp_iter qui renvoie un   itérateur qui itère sur les clés du dictionnaire. [...] Ce   signifie que nous pouvons écrire

    for k in dict: ...
    

    ce qui est équivalent à, mais beaucoup plus rapide que

    for k in dict.keys(): ...
    

    aussi longtemps que la restriction sur les modifications apportées au dictionnaire   (soit par la boucle ou par un autre thread) ne sont pas violés.

  • Ajoutez des méthodes aux dictionnaires qui renvoient différents types de   itérateurs explicitement:

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


325
2017-07-20 23:52



Itérer sur un dict itère à travers ses touches dans aucun ordre particulier, comme vous pouvez le voir ici:

Edit: (Ceci est plus le cas dans Python3.6, mais notez que c'est pas garantie comportement encore)

>>> d = {'x': 1, 'y': 2, 'z': 3} 
>>> list(d)
['y', 'x', 'z']
>>> d.keys()
['y', 'x', 'z']

Pour votre exemple, c'est une meilleure idée d'utiliser dict.items():

>>> d.items()
[('y', 2), ('x', 1), ('z', 3)]

Cela vous donne une liste de tuples. Lorsque vous bouclez sur eux comme ceci, chaque tuple est déballé dans k et v automatiquement:

for k,v in d.items():
    print(k, 'corresponds to', v)

En utilisant k et v comme noms de variables lors de la boucle sur un dict est assez commun si le corps de la boucle n'est que de quelques lignes. Pour des boucles plus compliquées, 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))

151
2017-07-21 01:27



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)

42
2017-07-20 23:49



Lorsque vous parcourez des dictionnaires en utilisant le for .. in ..-syntax, il itère toujours sur les clés (les valeurs sont accessibles en utilisant dictionary[key]).

Pour itérer sur des paires clé-valeur, utilisez for k,v in s.iteritems().


39
2017-07-20 22:29



C'est un idiome en boucle très commun. in est un opérateur. Pour quand utiliser for key in dict et quand ça doit être for key in dict.keys() voir L'article Idiomatic Python de David Goodger.


20
2017-07-20 22:42



Vous pouvez utiliser ceci:

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

9
2018-01-14 14:42



J'ai un cas d'utilisation où je dois parcourir la dict pour obtenir la clé, la paire de valeurs, ainsi que l'index indiquant où je suis. C'est comme ça que 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é, valeur est importante, sans les parenthèses, vous obtenez un ValueError "pas assez de valeurs à décompresser".


6
2018-05-25 13:42



Itérer sur les dictionnaires à l'aide de boucles "for"

d = {'x': 1, 'y': 2, 'z': 3} 
for key in d:
    ...

Comment Python reconnaît-il qu'il lui suffit de lire la clé du   dictionnaire? Est-ce que la clé est un mot spécial en Python? Ou est-ce simplement un   variable?

Ce n'est pas seulement for boucles. Le mot important ici est "itérer".

Un dictionnaire est un mappage des clés aux valeurs:

d = {'x': 1, 'y': 2, 'z': 3} 

Chaque fois que nous itérons, nous parcourons les clés. Le nom de la variable key est seulement destiné à être descriptif - et il est tout à fait approprié pour le but.

Cela arrive dans une compréhension de liste:

>>> [k for k in d]
['x', 'y', 'z']

Cela arrive quand nous passons le dictionnaire à la liste (ou tout autre objet de type collection):

>>> list(d)
['x', 'y', 'z']

La façon dont Python itère est, dans un contexte où il le faut, il appelle le __iter__ méthode de l'objet (dans ce cas le dictionnaire) qui renvoie un itérateur (dans ce cas, un objet keyiterator):

>>> d.__iter__()
<dict_keyiterator object at 0x7fb1747bee08>

Nous ne devrions pas utiliser nous-mêmes ces méthodes spéciales, mais 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 un __next__ méthode - 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

Quand un itérateur est épuisé, il soulève StopIteration. Voilà comment Python sait sortir d'un for boucle, ou une compréhension de liste, ou une expression de générateur, ou tout autre contexte itératif. Une fois qu'un itérateur relance StopIteration cela le soulèvera toujours - si vous voulez recommencer, vous en aurez 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 des dits itérer dans de nombreux contextes. Ce que nous avons vu, c'est que chaque fois que nous ectitons une dictée, nous obtenons les clés. Retour à l'exemple original:

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 le .values méthode 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 comme ceci:

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.


4
2018-06-21 02:51